Stack rolling and stack unrolling refer to the process of managing the stack memory during function calls, especially in recursive functions.
Stack rolling happens when a function is called and a new stack frame is created to hold that function's parameters, local variables, and return address. This process is sometimes referred to as "pushing" onto the stack because each new function call pushes a new frame onto the stack.
Example:
#include <stdio.h>
void functionA() {
int a = 10; // Local variable
printf("Inside functionA\n");
}
void functionB() {
functionA(); // functionA is called, creating a new stack frame
}
int main() {
functionB(); // functionB calls functionA, and the stack rolls
return 0;
}
functionB() calls functionA(), the stack rolls (a new stack frame for functionA() is pushed onto the stack).functionA().Stack unrolling is the reverse process of stack rolling. When a function call is completed, its stack frame is removed from the call stack (popped), and control returns to the calling function. This process is essential for cleaning up memory and maintaining the correct execution flow.
Example of Stack Unrolling:
#include <stdio.h>
void functionA() {
printf("Inside functionA\n");
}
int main() {
functionA(); // After functionA finishes, stack unrolling occurs
return 0;
}
functionA() completes, its stack frame is popped off the stack, and execution returns to main().In recursive functions, stack rolling and unrolling occur repeatedly as functions call themselves. Every recursive call creates a new stack frame, and when the recursion reaches the base case, the function begins returning, causing the stack to unroll.
#include <stdio.h>
void recursive(int n) {
if (n > 0) {
printf("%d\n", n);
recursive(n - 1); // Recursive call, rolling the stack
}
}
int main() {
recursive(3); // Calls recursive(3), which rolls the stack
return 0;
}
recursive(3) calls recursive(2), the stack rolls.n reaches 0, the recursion starts to return, and the stack begins to unroll.In C programming, headers are files that typically contain declarations of functions, macros, constants, and types. These files allow functions and variables to be used in multiple source files by providing a way to declare interfaces between different parts of a program.
A header file typically has a .h extension and contains:
For example, the header file math.h provides functions like sin(), cos(), etc., for mathematical operations.
// math_operations.h
#ifndef MATH_OPERATIONS_H
#define MATH_OPERATIONS_H
int add(int a, int b); // Function prototype for add
int subtract(int a, int b); // Function prototype for subtract
#endif
// main.c
#include <stdio.h>
#include "math_operations.h" // Including the custom header file
int main() {
int sum = add(3, 5);
int diff = subtract(10, 4);
printf("Sum: %d, Difference: %d\n", sum, diff);
return 0;
}
In this example:
math_operations.h contains the function prototypes for add() and subtract().main.c includes this header and calls the functions.In C, functions can accept arguments in two primary ways: by value and by reference. The distinction is crucial for understanding how data is passed between functions and whether modifications to arguments affect the calling function's variables.
When arguments are passed by value, a copy of the variable is passed to the function. This means that any changes made to the parameter inside the function do not affect the original variable.
Example:
#include <stdio.h>
void byValue(int x) {
x = 10; // Modifying the local copy of x
}
int main() {
int num = 5;
byValue(num);
printf("num after byValue: %d\n", num); // num remains 5
return 0;
}
num is passed by value to the function byValue(). The x inside byValue() is a copy of num, so changes to x don't affect the original num.When arguments are passed by reference, the function receives the address (memory location) of the variable, not a copy. This means that changes to the parameter inside the function directly affect the original variable.
In C, we typically simulate passing by reference using pointers.
Example:
#include <stdio.h>
void byReference(int *x) {
*x = 10; // Modifying the value at the address pointed to by x
}
int main() {
int num = 5;
byReference(&num); // Passing the address of num
printf("num after byReference: %d\n", num); // num is now 10
return 0;
}
num is passed by reference to the function byReference() by passing its memory address using the & operator. Inside the function, the value at that memory address is modified, so the change is reflected in the original variable num.Stack Rolling and Unrolling:
Headers:
#include <stdio.h> or #include "my_header.h".Passing Arguments by Value and by Reference:
Understanding these concepts is fundamental to managing memory, working with functions, and efficiently passing data between different parts of a C program.
Open this section to load past papers