I've written the below code on the fly! It seems to run good! It implements a stack management with stack overflow/underflow controls.
The main contains code to demonstrate the use of all the stack functions:
- int initStack(StackType * stack, size_t numOfElement);
- int freeStack(StackType * stack);
- int push(StackType * stack, int value);
- int mayPush(StackType *stack);
- int pop(StackType * stack, int * value);
- int pop2(StackType * stack);
- int mayPop(StackType *stack);
- StackError getError(StackType * stack);
The code uses the following basic stack operations:
- stack init: sp="stack dimension".
- push: stack[--sp]=value;
- pop: stack[sp++]=value;
- Stack overflow: (sp==0) [when we try to push a value]
- Stack underflow: (sp=="stack dimension") [when we try to pop a value]
The code:
#include <stdio.h>
#include <malloc.h>
typedef enum {
    NO_ERROR,
    MEMORY_ERROR,
    STACK_OVERFLOW,
    STACK_UNDERFLOW
} StackError;
typedef struct {
    int * stack;
    size_t numOfElem;
    size_t sp;     //stack pointer
    StackError err;
} StackType;
int initStack(StackType * stack, size_t numOfElement);
int freeStack(StackType * stack);
int push(StackType * stack, int value);
int mayPush(StackType *stack);
int pop(StackType * stack, int * value);
int pop2(StackType * stack);
int mayPop(StackType *stack);
StackError getError(StackType * stack);
int initStack(StackType * stack, size_t numOfElement)
{
    if ( (stack->stack=malloc(sizeof(*stack->stack)*numOfElement))==NULL ) {
        stack->err=MEMORY_ERROR;
        return stack->err;
    }
    stack->err=NO_ERROR;
    stack->numOfElem=numOfElement;
    stack->sp=numOfElement;       //The stack is void!
    return stack->err;
}
int freeStack(StackType * stack)
{
    if (stack->stack==NULL){
        stack->err=MEMORY_ERROR;
        return stack->err;
    }
    stack->err=NO_ERROR;
    free(stack->stack);
    stack->stack=NULL;
    return stack->err;
}
int push(StackType * stack, int value)
{
    if (stack->stack==NULL) {
        stack->err=MEMORY_ERROR;
        return stack->err;
    }
    if (!stack->sp) {
        stack->err=STACK_OVERFLOW;
        return stack->err;
    }
    stack->err=NO_ERROR;
    stack->stack[--stack->sp]=value;
    return stack->err;
}
int pop(StackType * stack, int * value)
{
    if (stack->stack==NULL) {
        stack->err=MEMORY_ERROR;
        return stack->err;
    }
    if (stack->sp>=stack->numOfElem) {
        stack->err=STACK_UNDERFLOW;
        return stack->err;
    }
    stack->err=NO_ERROR;
    *value=stack->stack[stack->sp++];
    return stack->err;
}
int pop2(StackType * stack)
{
    int value;
    pop(stack,&value);
    return value;
}
int mayPush(StackType *stack)
{
    return (stack->stack!=NULL && stack->sp>0)?1:0;
}
int mayPop(StackType *stack)
{
    return (stack->stack!=NULL && stack->sp<stack->numOfElem)?1:0;
}
StackError getError(StackType * stack)
{
    return stack->err;
}
int main(void)
{
    StackType stack;
    int res,i,j;
    size_t max=20;
    if ( (res=initStack(&stack, max))!=NO_ERROR ) {
        printf("Error: %d\n",res);
        return res;
    }
    //Fill the stack;
    printf("Pushing: ");
    i=0;
    while(mayPush(&stack)) {
        push(&stack,++i);
        printf("%d ",i);
    }
    puts("");
    //Try to push another element into the stack
    res=push(&stack,i);
    if (res!=NO_ERROR) {
        printf("Push error: %d\n",res);
    }
    //Read all the stack
    printf("Popping: ");
    while(mayPop(&stack)) {
        printf("%d ",pop2(&stack));
    }
    puts("");
    //Try to pop another element into the stack form 1
    res=pop(&stack,&i);
    if (res!=NO_ERROR) {
        printf("Pop error: %d\n",res);
    }
    //Try to pop another element into the stack form 2
    i=pop2(&stack);
    res=getError(&stack);
    if (res!=NO_ERROR) {
        printf("Pop error: %d\n",res);
    }
    //Fill an half of the stack
    printf("Pushing: ");
    for(i=1;i<=(int)max/2;i++) {
        push(&stack,i);
        printf("%d ",i);
    }
    puts("");
    //Get some value from the stack
    printf("Popping: ");
    for(i=1;i<=(int)max/4;i++) {
        printf("%d ",pop2(&stack));
    }
    puts("");
    //Put some value in the stack (also generates errors)
    for (j=0;j<3;j++) {
        printf("Pushing: ");
        for(i=1;i<=(int)max/3;i++) {
            printf("%d ",i*3+j);
            if ( (res=push(&stack,i*3+j))!=NO_ERROR ) {
                printf("Push error: %d\n",res);
            }
        }
        puts("");
    }
    //Get some value from the stack (also generates errors)
    printf("Popping: ");
    for(i=0;i<(int)max+2;i++) {
        if ( (res=pop(&stack,&j))!=NO_ERROR ) {
            printf("\nPop error: %d",res);
        } else {
            printf("%d ",j);
        }
    }
    puts("");
    puts("Deallocating the stack!");
    freeStack(&stack);
    printf("Pushing: ");
    if ( (res=push(&stack,415))!=NO_ERROR ) {
        printf("Push error: %d\n",res);
    }
    puts("Re-Deallocating the stack!");
    if ( (freeStack(&stack))!=NO_ERROR ) {
        printf("freeStack Error: %d\n",res);
    }
    return 0;
}