In an earlier post I included the header file and why all
kinds of variables should be there in the struct of our stack. This post is
about the implementation of the functions and their prototypes.
First lets look at the implementation and then we will see
why this and that happens in a particular way.
#include <stdio.h> #include <stdlib.h> #include "stack.h" void newStack(Stack* stack,int size,int elementSize,void (*clearmem)(void* )){ stack->size=size; stack->currentIndex=0; stack->items=malloc(size*elementSize); stack->elementSize=elementSize; stack->clearmem=clearmem; } void push(Stack* stack,void* item){ if(stack->currentIndex>=stack->size){ printf("not enough space"); return; }else{ void* addr=(char*)stack->items+(stack->currentIndex*stack->elementSize); memcpy(item,addr,stack->elementSize); stack->currentIndex++; } } void pop(Stack* stack,void* destination){ if(stack->currentIndex<=0){ printf("sorry empty stack"); return; }else{ stack->currentIndex--; memcpy((char*)stack->items+(stack->currentIndex*stack->elementSize),destination,stack->elementSize); } } void dispose(Stack* stack){ if(stack->clearmem!=NULL){ while(stack->currentIndex>=0){ stack->currentIndex--; stack->clearmem((char*)stack->items+(stack->currentIndex*stack->elementSize)); } } free(stack->items); }
Now the newStack function dosent do anything interesting
instead it just initializes the stuff in our struct. The push function has some
interesting stuff. The idea of the function is we copy everything from the
starting address given with void* to the stack covering the length of a single
item (we got it when we initialized our stack). Interesting thing here is how
to compute the address within our stack memory block.
Void dosent associate size information. That is if you have
int* I and you say i+1 you would get the address of the byte that is 4 bytes a
way from the starting address. This happens because we know that int is 4 bytes
long (normally). But since we are dealing with void first we cast it in to a
char* so that it would be assumed as one byte long and pointer arithmetic would
be like normal calculation. That is if we have char* c and we do c+1 it would
give the address of the byte that is 1 byte away from the starting address.
Now to the pop function. Why that is needed and address to
place the item in the stack instead of just returning the address within our
stack. Well think of what happens when one push another item after the pop we
would overwrite it. That’s not what we want right?. Other thing is the pointer
arithmetic which is mentioned above.
Finally, the dispose function destroys the stack and its
content. We are not responsible for freeing up memory for items that was poped
instead we would do the cleanup for items that are still in the stack by using
the memclear function given to us by our client at the initialization. After
cleaning items we would free the memory that was allocated for our stack using
free function.
Now its done