2. Introduction to Functions
• Building blocks of modular programming
• Break complex problems into smaller, manageable pieces
• Promote code reuse and maintainability
3. Function Syntax
• Basic structure of a C function:
return_type function_name(parameter_list) {
// function body
return value;
}
4. Function Declaration vs Definition
• Declaration (prototype)
• Definition
int add(int x, int y);
int add(int x, int y) {
return x + y;
}
5. Function Parameters
• Parameters are variables used to pass data to functions
• Pass by value:
void modify(int x) {
x = x + 1; // Only modifies local copy
}
int main() {
int a = 5;
modify(a); // a remains 5
return 0;
}
6. Pass by Reference
• Using pointers to modify original values:
void modify(int *x) {
*x = *x + 1; // Modifies original value
}
int main() {
int a = 5;
modify(&a); // a becomes 6
return 0;
}
7. Global Variables
• Declared outside all functions
• Accessible throughout the program
int globalVar = 10; // Global variable
void function1() {
globalVar++; // Can access and modify
}
void function2() {
printf("%d", globalVar); // Can read
}
8. Local Variables
• Declared inside functions
• Scope limited to the containing block
void function() {
int localVar = 5; // Local variable
{
int blockVar = 10; // Block scope
}
// blockVar not accessible here
}
// localVar not accessible here
9. Static Local Variables
• Retain value between function calls
void counter() {
static int count = 0; // Initialized only once
count++;
printf("%dn", count);
}
10. Variable Scope Rules
• Scope hierarchy example
int global = 10;
void function() {
int local = 20;
{
int local = 30; // Hides outer local
printf("%dn", local); // Prints 30
}
printf("%dn", local); // Prints 20
}
11. Stack Frames
• Memory organization for function calls
• Each function call creates a new stack frame
• Contains:
• Local variables
• Parameters
• Return address
• Saved registers
void function(int x) {
int y = x + 1;
// Stack frame contains:
// - Parameter x
// - Local variable y
// - Return address
}
12. Function Call Stack
• Example of multiple function calls:
void function3() {
int z = 3;
}
void function2() {
int y = 2;
function3();
}
void function1() {
int x = 1;
function2();
}
13. Recursive Function Call
int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
// Each recursive call creates a new stack frame
14. Memory Layout
• Program memory organization:
• Text segment (code)
• Data segment (global variables)
• Stack (function calls)
• Heap (dynamic allocation)
15. Stack Overflow
• Example of dangerous recursion:
void infinite_recursion() {
int large_array[1000]; // Local array
infinite_recursion(); // Will cause stack overflow
}
16. Return Values
• Common return types: void, int, float, char, etc.
• Different ways to return data:
• Simple type
• Complex type: pointers
• Struct type
int return_value() {
return 42;
}
void return_pointer(int* result) {
*result = 42;
}
struct Point return_struct() {
struct Point p = {1, 2};
return p;
}
17. Function Pointers
• Store address of functions, can be used to call such functions
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int main() {
int (*operation)(int, int);
operation = add;
printf("%dn", operation(5, 3)); // Prints 8
operation = subtract;
printf("%dn", operation(5, 3)); // Prints 2
return 0;
}
18. Function Pointers
• Function pointers can be used as parameters:
int apply(int (*func)(int), int value) {
return func(value);
}
int square(int x) {
return x * x;
}
// Usage:
int result = apply(square, 5); // Returns 25
19. Functions with varied parameter list
#include <stdarg.h>
int sum(int count, ...) {
va_list args;
va_start(args, count);
int total = 0;
for (int i = 0; i < count; i++) {
total += va_arg(args, int);
}
va_end(args);
return total;
}
21. Recursion
• Function calling itself:
int fibonacci(int n) {
if (n <= 1) return n;
return fibonacci(n-1) + fibonacci(n-2);
}
int factorial_tail(int n, int accumulator) {
if (n <= 1) return accumulator;
return factorial_tail(n - 1, n * accumulator);
}
22. Function Overloading
• C doesn't support overloading. Functions cannot have the same name
• Alternative approaches:
int add_int(int a, int b) {
return a + b;
}
float add_float(float a, float b) {
return a + b;
}
23. Function Documentation
• Using comments effectively:
• @brief Calculates the sum of two integers
• @param a First integer
• @param b Second integer
• @return Sum of a and b
/**
* @brief Calculates the sum of two integers
* @param a First integer
* @param b Second integer
* @return Sum of a and b
*/
int add(int a, int b) {
return a + b;
}
24. Error Handling
• Return codes and error checking:
int divide(int numerator, int denominator, int* result) {
if (denominator == 0) {
return -1; // Error code
}
*result = numerator / denominator;
return 0; // Success
}
25. Function Composition
• Combining multiple functions:
int process_data(int data) {
data = validate(data);
data = transform(data);
data = format(data);
return data;
}
26. Callback Functions
• Functions as parameters:
void process_array(int arr[], int size, void (*callback)(int)) {
for (int i = 0; i < size; i++) {
callback(arr[i]);
}
}
void print_item(int x) {
printf("%dn", x);
}
27. Header Files
• Function declarations in headers:
// math_functions.h
#ifndef MATH_FUNCTIONS_H
#define MATH_FUNCTIONS_H
int add(int a, int b);
int subtract(int a, int b);
#endif
29. Summary
• Functions are fundamental to C programming
• Understanding scope and lifetime is crucial
• Stack frame management affects program behavior
• Proper function design leads to maintainable code