C pointer based growable stack This is my first attempt at writing a C program, it a generic stack that can grow accordingly. It appears to work correctly, however I am worried that is just a fluke and I could be doing something very wrong.

I would greatly appreciate any feedback/criticism.

I am aware I should split this out into a .h and .c file but for demonstration purposes I have listed it as one.

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

typedef struct Stack
{
    void** data;
    int capacity;
    int count;
} Stack;

void stack_init(Stack *stack, int capacity)
{
    stack-&gt;data = (void**)malloc(capacity * sizeof(void*));
    stack-&gt;capacity = capacity;
    stack-&gt;count = 0;
}

void stack_push(Stack *stack, void* entry)
{
    if (stack-&gt;count &gt;= stack-&gt;capacity)
    {
        stack-&gt;capacity *= 2;
        stack-&gt;data = (void**)realloc(stack-&gt;data, stack-&gt;capacity * sizeof(void*));
    }

    stack-&gt;data[stack-&gt;count] = entry;
    stack-&gt;count++;
}

void* stack_pop(Stack *stack)
{
    stack-&gt;count--;
    return stack-&gt;data[stack-&gt;count];
}

bool stack_is_empty(Stack *stack)
{
    return (stack-&gt;count == 0);
}

int main()
{
    Stack myStack;

    stack_init(&amp;myStack, 2);

    for (int i = 0; i &lt; 2; i++)
    {
        stack_push(&amp;myStack, i);
    }

    while (!stack_is_empty(&amp;myStack))
    {
        printf("%d\n", (int)stack_pop(&amp;myStack));
    }

    return 0;
}
I suggest that you do more error checking:


malloc or realloc may fail.
I can initialize the stack with negative capacity.
I can pop more elements than I pushed.


In all these cases, your implementation silently swallows the errors and accesses invalid addresses.

As πάντα ῥεῖ said in comments, if you want to store generic elements that exceed void* in size, you need to allocate memory for them and let the void* point to them, e.g.:

typedef struct {
    // ...
} BigStruct;

// pushing
BigStruct* data = malloc(sizeof(BigStruct));
// initialize *data
stack_push(&amp;stack, data);

// popping
BigStruct* data = stack_pop(&amp;stack);
// use *data
free(data);


Some small issues:


It is not common to cast the result of malloc or realloc in C.
If the stack is initialized to capacity 0, then the stack will never grow and elements will be stored at invalid positions.  A solution is to adjust the capacity to 1 automatically.