Stack using array

An array-based stack stores elements in a contiguous block of memory and tracks the top with an integer index. Push and pop at the top are O(1) time. The trade-off is a fixed maximum capacity (unless you switch to a dynamic array). This page uses the common convention top == -1 for an empty stack and top == capacity - 1 when full.

On this page
  • Representation — array, top, and capacity
  • Operations — how push, pop, and peek update the index
  • Example in C — struct, init, full/empty, push/pop/peek
  • Trade-offs — vs linked list and dynamic growth

1) Array representation

You need a place to hold values, a record of where the top is, and a limit on how many items fit. At its simplest that is just an array and an integer top (you can group both in a struct later for convenience).

Typical fields for an array stack in C
Component Role Notes
items[] Stores stack elements from index 0 up to top. Can be int, double, or a typedef type; same idea for larger structs.
top Index of the current top element; -1 means empty. Some codebases use top as “next free slot” instead—stay consistent in one project.
Capacity Maximum number of elements (MAX macro or field). Stack is full when top == capacity - 1 (with top == -1 empty).

2) Mapping operations to the array

All mutations adjust top by one and read or write items[top]. Always check full before push and empty before pop or peek.

Stack operations with top == -1 when empty
Operation Array steps Failure case
push(x) If not full: top++, then items[top] = x. Overflow if already full.
pop If not empty: read items[top], then top--. Underflow if empty.
peek If not empty: return items[top] without changing top. Underflow if empty.
isEmpty True when top < 0 (or top == -1).
isFull True when top == capacity - 1.

3) Example in C

Below, the stack is a fixed int array plus an index top, both kept at file scope with static so helpers need no struct, no pointer parameters, and no & in main. Functions return 1 on success and 0 on overflow or underflow; after a successful peek or pop, read the value from stack_last.

#include <stdio.h>

#define MAX 100

/* One stack for this file: elements live in stack[0..top], top == -1 when empty. */
static int stack[MAX];
static int top;

/* After stack_peek or stack_pop returns 1, the top value is here (no extra out-parameters). */
static int stack_last;

void stack_init(void) {
    top = -1;
}

int stack_is_empty(void) {
    return top < 0;
}

int stack_is_full(void) {
    /* Last valid index is MAX - 1, so full when top sits there. */
    return top >= MAX - 1;
}

/* Returns 1 on success, 0 if overflow (array full). */
int stack_push(int value) {
    if (stack_is_full())
        return 0;
    top++;
    stack[top] = value;
    return 1;
}

/* Returns 1 on success, 0 if underflow (empty). Popped value is stored in stack_last. */
int stack_pop(void) {
    if (stack_is_empty())
        return 0;
    stack_last = stack[top];
    top--;
    return 1;
}

/* Returns 1 on success, 0 if underflow. Current top (without removing) is stack_last. */
int stack_peek(void) {
    if (stack_is_empty())
        return 0;
    stack_last = stack[top];
    return 1;
}

int main(void) {
    stack_init();

    stack_push(10);
    stack_push(20);

    if (stack_peek())
        printf("peek: %d\n", stack_last);

    if (stack_pop())
        printf("pop: %d\n", stack_last);

    return 0;
}

This layout is easy to read; larger programs usually pass the array and top explicitly or wrap them in a type so you can have more than one stack.

Explanation of the program output

Here’s the explanation of the program’s output in table format:

Program execution trace
Step Operation Stack state (top to bottom) Return value stack_last value Output
1 stack_init() [] (empty, top = -1) (void) unchanged (none)
2 stack_push(10) [10] (top = 0) 1 (success) unchanged (none)
3 stack_push(20) [20, 10] (top = 1) 1 (success) unchanged (none)
4 stack_peek() [20, 10] (unchanged, top = 1) 1 (success) 20 (top value) peek: 20
5 stack_pop() [10] (top = 0) 1 (success) 20 (popped value) pop: 20
6 Program ends [10] (still in stack)
Final output
Line Output
1 peek: 20
2 pop: 20

Key points

Behavior Explanation
Peek shows 20 Stack is LIFO (Last-In-First-Out), so the most recent push (20) is on top.
Pop shows 20 The same top element (20) is removed and returned.
No output for pushes stack_push() returns a success code but doesn’t print anything.
10 remains The program ends before popping the remaining element (10).

4) Trade-offs

  • Pros — Very fast and simple; excellent cache locality; no malloc per push if the array is static or allocated once.
  • Cons — Fixed cap causes overflow unless you resize; wasted space if you allocate huge MAX but use little.

For unbounded growth from an array, use a dynamic array stack; for no fixed cap without contiguous resizing, compare with a linked-list stack. Operation definitions are summarized on Stack operations.

Key takeaway

Keep one clear invariant: top always points at the current top element, or is -1 when empty. Every push increments top then assigns; every pop reads then decrements—after checking full and empty.

Next up: Stack using dynamic array · Stack using linked list · Stack operations