Functions
## Learning Objectives
- Define and call functions
- Understand parameters and return values
- Master function declarations
- Learn recursion
## Defining Functions
### Basic Structure
```c
#include
void greet(void) {
printf("Hello!\n");
}
int main(void) {
greet();
return 0;
}
```
### Function with Return Type
```c
int add(int a, int b) {
return a + b;
}
```
### Calling Functions
```c
#include
int add(int a, int b) {
return a + b;
}
int main(void) {
int sum = add(5, 3);
printf("%d\n", sum);
return 0;
}
```
## Parameters and Arguments
### Passing Arguments
```c
void printName(const char *name) {
printf("Name: %s\n", name);
}
int main(void) {
printName("Alice");
return 0;
}
```
### Multiple Parameters
```c
int calculateArea(int width, int height) {
return width * height;
}
int main(void) {
int area = calculateArea(5, 10);
printf("%d\n", area);
return 0;
}
```
### Parameter Order Matters
```c
// Correct order
int result = calculate(10, 5); // 10 - 5 = 5
int calculate(int a, int b) {
return a - b;
}
```
## Return Values
### void (No Return)
```c
void printHello(void) {
printf("Hello\n");
}
```
### Return Early
```c
char getGrade(int score) {
if (score >= 90) return 'A';
if (score >= 80) return 'B';
if (score >= 70) return 'C';
return 'F';
}
```
### Multiple Returns (Guard Clauses)
```c
int validate(int age, const char *name) {
if (age < 0) return 0;
if (name == NULL) return 0;
return 1;
}
```
## Function Declarations
### Prototype
```c
// Declaration (prototype)
int add(int a, int b);
int main(void) {
int sum = add(5, 3);
return 0;
}
// Definition
int add(int a, int b) {
return a + b;
}
```
### Header File (math_utils.h)
```c
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
int add(int a, int b);
int subtract(int a, int b);
int multiply(int a, int b);
int divide(int a, int b);
#endif
```
### Implementation (math_utils.c)
```c
#include "math_utils.h"
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
int multiply(int a, int b) {
return a * b;
}
int divide(int a, int b) {
if (b == 0) return 0;
return a / b;
}
```
## Pass by Value
### Primitives (Pass by Value)
```c
void doubleIt(int x) {
x = x * 2; // Only affects local copy
}
int main(void) {
int num = 5;
doubleIt(num);
printf("%d\n", num); // Still 5
return 0;
}
```
### To Modify, Use Pointers
```c
void doubleIt(int *x) {
*x = *x * 2; // Modifies original
}
int main(void) {
int num = 5;
doubleIt(&num);
printf("%d\n", num); // 10
return 0;
}
```
## Arrays as Parameters
### Array Decays to Pointer
```c
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main(void) {
int nums[] = {1, 2, 3, 4, 5};
printArray(nums, 5); // Array name is pointer
return 0;
}
```
### With Pointer Syntax
```c
void printArray(int *arr, int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]); // or *(arr + i)
}
printf("\n");
}
```
### Prevent Modification
```c
int sum(const int *arr, int size) {
int total = 0;
for (int i = 0; i < size; i++) {
total += arr[i]; // Can read, cannot modify
}
return total;
}
```
## Static Functions
### File Scope Only
```c
static int helper(int x) {
return x * 2;
}
int publicFunction(int x) {
return helper(x); // Can call static function
}
```
- `static` functions are only visible within the file
- Used for helper functions not meant to be exported
## Recursion
### Function Calling Itself
```c
int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
```
Call sequence for `factorial(5)`:
```text
factorial(5) = 5 * factorial(4)
factorial(4) = 4 * factorial(3)
factorial(3) = 3 * factorial(2)
factorial(2) = 2 * factorial(1)
factorial(1) = 1
Result: 5 * 4 * 3 * 2 * 1 = 120
```
### Iterative Alternative
```c
int factorial(int n) {
int result = 1;
for (int i = 2; i <= n; i++) {
result *= i;
}
return result;
}
```
### Fibonacci
```c
int fibonacci(int n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
```
### Tail Recursion
```c
int factorialTail(int n, int accumulator) {
if (n <= 1) return accumulator;
return factorialTail(n - 1, n * accumulator);
}
int factorial(int n) {
return factorialTail(n, 1);
}
```
## Function Pointers
### Declaration
```c
int (*funcPtr)(int, int); // Pointer to function returning int
```
### Usage
```c
int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }
int main(void) {
int (*operation)(int, int);
operation = add;
printf("%d\n", operation(5, 3)); // 8
operation = multiply;
printf("%d\n", operation(5, 3)); // 15
return 0;
}
```
### Callback Pattern
```c
void apply(int *arr, int size, int (*func)(int)) {
for (int i = 0; i < size; i++) {
arr[i] = func(arr[i]);
}
}
int square(int x) { return x * x; }
int main(void) {
int nums[] = {1, 2, 3, 4, 5};
apply(nums, 5, square);
// nums is now {1, 4, 9, 16, 25}
return 0;
}
```
## Variable Arguments (varargs)
### stdarg.h
```c
#include
#include
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;
}
int main(void) {
printf("%d\n", sum(3, 1, 2, 3)); // 6
printf("%d\n", sum(5, 1, 2, 3, 4, 5)); // 15
return 0;
}
```
## Summary
- Functions: `return_type name(params) { }`
- Function prototypes declare before use
- Pass by value for primitives
- Use pointers to modify arguments
- Arrays decay to pointers when passed
- `static` functions are file-local
- Recursion: ensure base case exists
- `varargs` for variable arguments
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →