Q:

Which is a better implementation of a stack data structure (based on an array)?

This is a version I made:
#include <stdio.h>
#include <stdbool.h>

#define MAX_STACK_SIZE 255

typedef struct
{
    int array[MAX_STACK_SIZE];
    unsigned int count;
    unsigned int max;
} Stack;

void initialize(Stack*);
void push(Stack*, int value);
int* pop(Stack*);
bool isEmpty(Stack*);
bool isFull(Stack*);

int main()
{
    Stack s1;
    initialize(&s1);
    for(int i = 0; i < 7; i++)
    {
        push(&s1, i);
    }
    pop(&s1);
    push(&s1, 88);
    push(&s1, 6);
    int *top;
    while((top = pop(&s1)) != NULL)
    {
        printf("Popping %d from the top of the stack.\n", *top);
    }
    return 0;
}

void initialize(Stack *p)
{
    p->count = 0;
    p->max = MAX_STACK_SIZE;
}

void push(Stack *p, int value)
{
    if(!isFull(p))
    {
        p->array[p->count] = value;
        p->count++;
    }
}

int* pop(Stack *p)
{
    if (!isEmpty(p))
    {
        p->count--;
        return p->array + p->count;
    }
    return NULL;
}

bool isEmpty(Stack *p)
{
    return p->count == 0;
}

bool isFull(Stack *p)
{
    return p->count == p->max;
}

This is a version of how it was done from the source I'm learning from:
#include <stdio.h>

#define MAX_STACK_SIZE 255
#define true 1
#define false 0
#define bool unsigned short int

struct stack
{
    int *topOfStack;
    int *pointer;
    int count;
    int max;
    int theStack[MAX_STACK_SIZE];
};

void initStack(struct stack *stackStruct)
{
    stackStruct->topOfStack = stackStruct->theStack;
    stackStruct->pointer = stackStruct->theStack;
    stackStruct->max = MAX_STACK_SIZE;
    stackStruct->count = 0;
}
bool pushStack(struct stack *stackStruct, int inputValue)
{
    if(stackStruct->count < stackStruct->max)
    {
        *stackStruct->pointer = inputValue;
        stackStruct->count++;
        stackStruct->pointer++;
        return true;
    }
    else
        return false;
}
int* popStack(struct stack *stackStruct)
{
    if(stackStruct->count > 0)
    {
        stackStruct->pointer--;
        stackStruct->count--;
        return stackStruct->pointer;
    }
    return NULL;
}

I think there's not so much of a difference between theb, but I just wanted to be sure.  In their version, they've used 2 additional pointers in their Stack struct and I removed them because I thought it was not necessary because we could use the array address + count to get the pointer address in their example.  I think they used it for convenience reasons.  More differences are that I included <stdbool.h> instead of using macros (not really important).
On top of that, I've implemented isEmpty() and isFull() methods just for convenience, but don't take it into account when comparing the two implementations since I'm sure they could do the same.  I just chose to show the 2 main functions that could be used on a stack.
Other than that, since it's an array-based implementation of a stack, I think it was possible to not include the max field in the struct since we define in a macro the stack maximum size, but I added it as well to my implementation for the heck of it.
Is there any differences between our implementations? Since I chose to do my own implementation I just want to make sure I that I did implemented it correctly and efficiently.

A:

push() and pop() have an asymmetry that should be reconciled.  push() does not indicate any thing special when the stack is full and a push is attempted.  It silently does not do the push.  Yet when an pop of an emty stack occurs, a NULL is returned (versus a pointer to int) allowing the calling routine to take evasive action.  A symmetric solution would both do something special - or not - on full/empty.
A function to inspect the top of stack, without popping, could be added.  This IMO would be useful.  Additional routines to report current stack depth or stack space left are something to consider.
Using unsigned int is OK, especially if the fixed array size is known to always be less than UINT_MAX.  I favor size_t for array indexing as it has better portability for large arrays.
A way to deal with popping or inspecting an empty stack is, as part of initialize(), to pass an int as the bottom-of-stack.  This value does not actually ever get "popped off".
The names of the functions are too generic ("initialize") and could well collide with other code.  Suggest something like Stack_initialize(), and Stack_push().
The OO part of me wants to see a copy and destructor function too.  The destructor could simple do count = max = 0;

