Stack in C Programming – Examples
- Stack may contains many frames
- One stack frame is assigned to each function call
- Frame size is fixed at compile time because each function depth is find out at compile time.
- One frame depth may contains Local Variables, Function Arguments, Return Address, Frame Pointer and many others.
- Entire Stack size is assigned by OS from reserved space for stack in main memory.
Stack Working Rule
The stack follows a Last-In, First-Out (LIFO) structure in memory.
Example: The stack works like a stack of plates: the last plate you put on the top is the first one you take off. Similarly, when you call a function, it goes on top of the stack. Once it finishes, it comes off the stack, and you go back to the previous function. This way, the most recent function always finishes first, just like the top plate comes off first.
Stack Layout
The stack starts at a high memory address and grows downwards and heap grows upwards. In between, there is initially unused memory (free space) that can be used by either the heap or stack as they grow.
- There is no fixed “cut mark” between the stack and heap. Instead, there’s a dynamic boundary that shifts as the stack and heap grow or shrink.
- If the stack and heap grow too large and meet each other, it can cause a memory collision, leading to errors like a stack overflow or heap overflow.
Note:
- The compiler determines that how much space each stack frame requires based on the function’s local variables, parameters, and any saved registers at compile time.
- The OS sets up the stack size, frame size and other memory management at run time.
Key Uses of the Stack:
When a function is called, a new frame along with its all data (i.e. Local Variables, Function Arguments, Return Address, Frame Pointer etc.) is pushed onto the stack, and when the function returns, that frame is popped off at runtime.
There are 3 main key points of stack
- Function calls: Each time a function is called, a “stack frame” is created, which contains:
- The function’s local variables.
- The return address (where the program should go after the function returns).
- The parameters passed to the function.
- Local Variables: Local variables inside a function are stored in the stack. They are created when the function is called and destroyed when the function exits.
- Control Flow: The stack helps manage the control flow of the program, especially with nested or recursive function calls.
Example of Stack Usage in C:
Let’s look at a simple example that illustrates how the stack is used in a C program.
#include <stdio.h> void funcA(int x) { int y = x + 2; // Local variable y stored in stack printf("In funcA, y = %d\n", y); } int main() { int a = 5; // Local variable a stored in stack printf("In main, a = %d\n", a); funcA(a); // a new stack frame pushes when Call to funcA return 0; // Return pops main's stack frame }
Steps of Stack Functionality
let’s explain the execution of the above program with great detail
Program Starts: The stack is initially empty when the program starts.
Step 01: main() Function Call: When the program enters the main() function, a stack frame for main() is created. The local variable a is stored in this frame.
Now stack look as following
Step 02: Calling funcA():
When funcA(a) is called, the current state of main() is saved and a new stack frame for funcA() is pushed onto the stack. The parameter x = 5 (passed from main) is stored in the funcA() stack frame, along with the local variable y.
Now stack position looks as following
Step 03 : After funcA() finishes, its entire stack frame is popped off, and the program returns to main(). The stack frame for funcA() is destroyed, freeing up the memory it used.
Now stack look as following
When main() finishes, its stack frame is popped off, and the stack becomes empty again.