Dynamically-sized stack - follow-up 2 Follow up of - Dynamically-sized stack - follow up

I've took the tips given to me, and what I did now is:


changing the function names to have a prefix
making the pop() function only popping and not returning the value as well
checking for OOM exception / scenario that 0 is passed to capacityIncrement variable when initializing the stack (in those cases, if trying to push values to the stack, just ignore)
added a decrement mechanism, when popping values a check will be made to see if there are (capacityIncrement / 2 + capacityIncrement) elements in the stack that are not in use, and if so, decrement the stack size by capacityIncrement




#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdbool.h&gt;

typedef struct
{
    int *elementData;
    unsigned int stackSize;
    unsigned int capacityIncrement;
    unsigned int elementCount;
} Stack;

void stack_initialize(Stack*, unsigned int);
void stack_push(Stack*, int);
void stack_pop(Stack*);
int stack_peek(const Stack*);
void stack_destroy(Stack*);
bool stack_isEmpty(const Stack*);
void stack_setCapacityIncrement(Stack*, unsigned int);
unsigned int stack_getCapacityIncrement(const Stack*);
unsigned int stack_getNumberOfElements(const Stack*);
unsigned int stack_getSize(const Stack*);

int main()
{
    Stack s1;
    stack_initialize(&amp;s1, 4);
    for(int i = 0; i &lt; 25; i++)
    {
        stack_push(&amp;s1, i + 1);
    }
    stack_pop(&amp;s1);
    stack_push(&amp;s1, 88);
    stack_push(&amp;s1, 25);
    printf("The top of the stack is %d.\n", stack_peek(&amp;s1));
    while(!stack_isEmpty(&amp;s1))
    {
        int top = stack_peek(&amp;s1);
        stack_pop(&amp;s1);
        printf("Popping %d from the top of the stack.\n", top);
        printf("Size of stack is %d.\n", s1.stackSize);
    }
    return 0;
}

void stack_initialize(Stack *p, unsigned int capacityIncrement)
{
    p-&gt;elementData = NULL;
    p-&gt;stackSize = 0;
    p-&gt;capacityIncrement = capacityIncrement;
    p-&gt;elementCount = 0;
}

void stack_push(Stack *p, int value)
{
    if (p-&gt;elementCount == p-&gt;stackSize)
    {
        int newStackSize = p-&gt;stackSize + p-&gt;capacityIncrement;
        void *temp = realloc(p-&gt;elementData, sizeof(*p-&gt;elementData) * newStackSize);
        if (temp == NULL || newStackSize == 0)
        {
            return;
        }
        p-&gt;stackSize = newStackSize;
        p-&gt;elementData = temp;
    }
    p-&gt;elementData[p-&gt;elementCount] = value;
    p-&gt;elementCount++;
}

void stack_pop(Stack *p)
{
    if (!stack_isEmpty(p))
    {
        p-&gt;elementCount--;
        if(p-&gt;stackSize - p-&gt;elementCount == p-&gt;capacityIncrement / 2 + p-&gt;capacityIncrement)
        {
            int newStackSize = p-&gt;stackSize - p-&gt;capacityIncrement;
            p-&gt;elementData = realloc(p-&gt;elementData, sizeof(*p-&gt;elementData) * newStackSize);
            p-&gt;stackSize = newStackSize;
        }
    }
}

int stack_peek(const Stack *p)
{
    if (!stack_isEmpty(p))
    {
        return p-&gt;elementData[p-&gt;elementCount - 1];
    }
    return 0;
}

void stack_destroy(Stack *p)
{
    free(p);
}

bool stack_isEmpty(const Stack *p)
{
    return p-&gt;elementCount == 0;
}

void stack_setCapacityIncrement(Stack *p, unsigned int capacityIncrement)
{
    p-&gt;capacityIncrement = capacityIncrement;
}

unsigned int stack_getCapacityIncrement(const Stack *p)
{
    return p-&gt;capacityIncrement;
}

unsigned int stack_getNumberOfElements(const Stack *p)
{
    return p-&gt;elementCount;
}

unsigned int stack_getSize(const Stack *p)
{
    return p-&gt;stackSize;
}
Use same case prefix for type "Stack" and functions "stack" --> "gStack" or whatever.
Use correct print specifier.  This implies that either OP does not have all warnings enabled or is using a weak compiler.  Suggest remedying that.

// printf("Size of stack is %d.\n", s1.stackSize);
printf("Size of stack is %u.\n", s1.stackSize);

Use consistent sign-ness

// int newStackSize;
unsigned newStackSize;

In push(), newStackSize test should be corrected or eliminated.

// if (temp == NULL || newStackSize == 0)

if (temp == NULL &amp;&amp; newStackSize &gt; 0)

// or if confident newStackSize will never be 0 here
if (temp == NULL)

Silently failing push() due to OOM is a concern.
pop() should do similar OOM protection as pop().  Even though it sounds silly that reducing memory usage should ever fail.
Consider putting all memory allocation into one helper function.  (BTW: destroy() did not free p-&gt;elementData.

static int stack_realloc(int **ptr, unsigned *oldsize, unsigned newsize) {
  if (newsize &gt; 0) {
    void *newptr = realloc(*ptr, newsize);
    if (newptr == NULL) return 1; // fail
    *ptr = newptr;
  }
  else {
    free(*ptr);
    *ptr = NULL;
  }
  *oldsize = newsize;
  return 0; // success;
}

// push()
unsigned newStackSize = p-&gt;stackSize + p-&gt;capacityIncrement;
if (stack_realloc(&amp;p-&gt;elementData, &amp;p-&gt;stackSize, newStackSize);

// pop()
// change from == to &gt;=
if(p-&gt;stackSize - p-&gt;elementCount &gt;= p-&gt;capacityIncrement / 2 + p-&gt;capacityIncrement) {
  unsigned newStackSize = p-&gt;stackSize - p-&gt;capacityIncrement;
  // No problem is realloc failed, just continue with current stack
  stack_realloc(&amp;p-&gt;elementData, &amp;p-&gt;stackSize, newStackSize);

// destroy() 
stack_realloc(&amp;p-&gt;elementData, &amp;p-&gt;stackSize, 0);
// Do not free `p`.
// free(p);