#include #include #define MAX_SIZE 5 // static array size typedef struct { void *data[MAX_SIZE]; //Level 2 int top; } PtrStack; // Initialize stack void initStack(PtrStack *s) { s->top = -1;} // Check if stack is empty int isEmpty(PtrStack *s) { return s->top == -1;} // Check if stack is full int isFull(PtrStack *s) { return s->top == MAX_SIZE - 1;} // Push pointer onto stack int push(PtrStack *s, void *ptr) { if (isFull(s)) { printf("Stack overflow! Cannot push.\n"); return 0; } s->data[++s->top] = ptr; return 1; } // Pop pointer from stack void *pop(PtrStack *s) { if (isEmpty(s)) { printf("Stack underflow! Cannot pop.\n"); return NULL; } return s->data[s->top--]; } // Get top element without removing it void *top(PtrStack *s) { if (isEmpty(s)) { printf("Stack is empty.\n"); return NULL; } return s->data[s->top]; } // Get current stack size int size(PtrStack *s) { return s->top + 1;} // Example object typedef struct { int id; Zchar name[32]; } Person; Person *newPerson(int id, const char *name) { Person *p = malloc(sizeof(Person)); //Level 3 p->id = id; snprintf(p->name, sizeof(p->name), "%s", name); return p; } // Example usage int main() { PtrStack stack; //Level 1 initStack(&stack); Person *p1 = newPerson(1, "Alice"); Person *p2 = newPerson(2, "Bob"); Person *p3 = newPerson(3, "Charlie"); push(&stack, p1); push(&stack, p2); push(&stack, p3); printf("Stack size: %d\n", size(&stack)); Person *t = (Person *)top(&stack); printf("Top element: id=%d name=%s\n", t->id, t->name); while (!isEmpty(&stack)) { Person *p = (Person *)pop(&stack); printf("Popped: id=%d name=%s\n", p->id, p->name); free(p); //Free p L3 } printf("Stack empty? %s\n", isEmpty(&stack) ? "Yes" : "No"); //Stack and Stack Array get free after the scope L1 (stack) and L2 (array of Ptr) return 0; }