A stack is a simple lastin, firstout (LIFO) data structure  the last data element stored on a stack is the first data element retrieved from it. The common analogy is a stack of plates in a cafeteria: when you go through the line, you pop the top plate off of the stack; the dishwasher (stepping away from reality a bit) pushes a single clean plate on top of the stack. So a stack supports two basic operations: push and pop. Some stacks also provide additional operations: size (the number of data elements currently on the stack) and peek (look at the top element without removing it).
Stacks are important data structures in their own right. Programmers can implement stacks in many ways, including arrays, which we do here as an array example. The bottom of the stack is the first array element (i.e., the element at index location 0). The stack top always changes as elements are pushed on and popped off the stack. So, we'll use a second variable, called a stack pointer, to keep track of the stack top. The stack pointer is an index into the array representing the stack.
Implementing a stack as an array has two problems. First, the size of the stack (i.e., the maximum number of elements that the stack can hold) must be a compiletime constant. Second, the type of data stored in the stack (i.e., the array type) is specified when the array is defined  when we write the code. We'll fix these problems as we refine our initial implementation in subsequent chapters, but we won't see the final, clean result until we cover templates near the end of the text.
The following discussion describes how stacks work generally and as implemented with arrays specifically. So, for now, we "solve" the two problems presented above by simply creating a stack that can only store characters implemented as a char array whose size is left ambiguous (specified as a symbolic constant implemented with macro, enum, or const).
char st[SIZE]; int sp = 0;
The various stack operations are easy to implement, but notice that push and pop use postincrement and predecrement respectively (this is crucial for the algorithm to work).
st[sp++] = data
(sp must be < SIZE)return st[sp]
(sp must be > 0)return sp;
return st[sp1]
Based on these operations, the snapshots shown in Figure 3 illustrate the appearance of a stack as data (characters) are stored in or pushed onto it.
Operation  Picture  Execution 

Stack is empty  
push('A'); 
st[0] = 'A'; sp = 0 + 1; 

push('B'); 
st[1] = 'B'; sp = 1 + 1; 

push('C'); 
st[2] = 'C'; sp = 2 + 1; 
st[sp++] = data
, where "data" is the function argument. The middle column abstractly illustrates how the stack (the array and the stack pointer) appears after each call to the push function. The right column breaks the behavior of the push function into two steps.
Similarly, we can retrieve the data (characters) stored on a stack by popping them off and returning them.
Operation  Picture  Execution 

data = pop(); 
sp = 3  1; return sp[2]; 

data = pop(); 
sp = 2  1; return sp[2]; 

data = pop(); 
sp = 1  1; return sp[2]; 
return st[sp]
. The middle column abstractly illustrates how the stack (the array and the stack pointer) appears after each call to the pop function. The right column breaks the pop function's behavior into two steps. Notice that the pop operations logically remove a character from the stack array  the program treats the slots at and above the stack pointer as empty  but the data remains in the array. So, the next push operation will overwrite the data at the stack pointer. The stack at the bottom of the table is logically empty.
Maintaining a stack as two discrete variables (an array and a stack pointer) is cumbersome, errorprone, and makes it difficult to support multiple stacks in a program. Fortunately, we can solve these problems (if somewhat inelegantly) if we implement a stack as a struct. But even after settling on a structurebased solution, there are still two possible paths that we can take. We base the first implementation on automatic or local variables and the second on dynamic or heap variables. More elegant solutions based on classes and templates will follow in subsequent chapters.