← Back to C series
🎯
Advanced
definition · call · recursion · static

Chapter 2 — Functions

Splitting a program into named, reusable pieces. Parameters, return values, recursion, and `static`.

functionrecursionstatic
Duration
1-2 hours
Level
📊 Intermediate
Prerequisite
🎯 Advanced 1
Outcome
Split code into reusable pieces; handle recursion

What you'll learn

  • 1Define and call functions with parameters and return value.
  • 2Understand pass-by-value vs pass-by-pointer.
  • 3Use recursion for problems that naturally divide.
  • 4Use `static` for internal helpers and persistent locals.

Core Concepts

1) Definition vs declaration (prototype)

c
// prototype (declaration) — usually in a header
int add(int a, int b);

// definition — usually in a .c file
int add(int a, int b) {
    return a + b;
}

Functions used before they're defined need a **prototype** above.

2) Pass-by-value

c
void noop(int x) { x = 100; }
int n = 5;
noop(n);
printf("%d\n", n);   // still 5 — caller untouched

C copies arguments. To mutate the caller's variable, pass a **pointer**.

3) Return types

c
int sum(int a, int b) { return a + b; }
double avg(int a, int b) { return (a + b) / 2.0; }
void print(const char *s) { printf("%s\n", s); }   // returns nothing

4) Recursion

c
int fact(int n) {
    if (n <= 1) return 1;
    return n * fact(n - 1);
}

Always have a **base case**, otherwise you stack-overflow.

5) `static`

UseEffect
`static` on file-scope functionVisible only inside this `.c` file (private)
`static` on local variableKeeps value between calls (initialized once)

Examples

Example 1 — `ex01_basic.c`: simple add

c
int add(int a, int b) {
    return a + b;
}
int main(void) {
    printf("%d\n", add(2, 3));
    return 0;
}

**Output**

text
5

Key: declare first or define before use; otherwise `-Wall` warns.

Example 2 — `ex02_recursion.c`: factorial

c
int fact(int n) {
    if (n <= 1) return 1;
    return n * fact(n - 1);
}
printf("%d\n", fact(5));

**Output**

text
120

Key: base case (`n <= 1`) prevents infinite recursion.

Example 3 — `ex03_array_param.c`: array as parameter (decays)

c
int sum(int *a, int n) {
    int s = 0;
    for (int i = 0; i < n; i++) s += a[i];
    return s;
}
int a[] = {1, 2, 3, 4};
printf("%d\n", sum(a, 4));

**Output**

text
10

Key: an array parameter is really a pointer — you must also pass the length.

Example 4 — `ex04_static.c`: per-call counter

c
void hit(void) {
    static int count = 0;
    count++;
    printf("called %d times\n", count);
}
hit(); hit(); hit();

**Output**

text
called 1 times
called 2 times
called 3 times

Key: `static` makes the local survive between calls, initialized once.

Common mistakes

  1. **No prototype** — implicit declaration warning, may pick wrong types.
  2. **Forgetting `return`** in non-void — undefined return value.
  3. **Returning a pointer to a local** — local goes out of scope; the pointer dangles.
  4. **No base case** — infinite recursion → stack overflow.

Recap

  • Prototypes go above first use; definitions live wherever.
  • C is pass-by-value; pass pointers to mutate the caller's data.
  • Recursion needs a base case.
  • `static` controls visibility and lifetime.

Try it

bash
cd src
gcc -std=c11 -Wall -o ex01 ex01_basic.c && ./ex01
gcc -std=c11 -Wall -o ex02 ex02_recursion.c && ./ex02
gcc -std=c11 -Wall -o ex03 ex03_array_param.c && ./ex03
gcc -std=c11 -Wall -o ex04 ex04_static.c && ./ex04

💻 Examples

Compilable, runnable examples — see the output yourself.

ex01_basic.csimple add
CODE
#include <stdio.h>

int add(int a, int b);
int max(int a, int b);
void print_line(void);

int main(void) {
    print_line();
    printf("add(3, 4) = %d\n", add(3, 4));
    printf("max(7, 2) = %d\n", max(7, 2));
    print_line();
    return 0;
}

int add(int a, int b) { return a + b; }
int max(int a, int b) { return a > b ? a : b; }
void print_line(void) { printf("--------------------\n"); }
▶ Output
5
ex02_recursion.cfactorial
CODE
#include <stdio.h>

long long factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}

long long fib(int n) {
    if (n < 2) return n;
    return fib(n - 1) + fib(n - 2);
}

int main(void) {
    for (int i = 0; i <= 10; i++) {
        printf("%2d! = %lld,  fib(%2d) = %lld\n",
               i, factorial(i), i, fib(i));
    }
    return 0;
}
▶ Output
120
ex03_array_param.carray as parameter (decays)
CODE
#include <stdio.h>

/*      */
int sum(const int arr[], int n) {
    int s = 0;
    for (int i = 0; i < n; i++) s += arr[i];
    return s;
}

double average(const int arr[], int n) {
    return (double)sum(arr, n) / n;
}

int main(void) {
    int data[] = {10, 20, 30, 40, 50};
    int n = (int)(sizeof(data) / sizeof(data[0]));

    printf("sum: %d\n", sum(data, n));
    printf("mean: %.2f\n", average(data, n));
    return 0;
}
▶ Output
10
ex04_static.cper-call counter
CODE
#include <stdio.h>

int counter(void) {
    static int count = 0;   /*     */
    count++;
    return count;
}

int main(void) {
    for (int i = 0; i < 5; i++) {
        printf(" %d -> %d\n", i + 1, counter());
    }
    return 0;
}
▶ Output
called 1 times
called 2 times
called 3 times

📝 Exercises

Try them yourself first, then open the solution to compare.

Exercise 1

Problem 1 (hw01.c)

Goal: Write recursive `int fib(int n)` and print `fib(0..10)`.

Requirements
  • Filename: hw01.c
Toggle solution
SOLUTION
#include <stdio.h>

int gcd(int a, int b) {
    if (b == 0) return a;
    return gcd(b, a % b);
}

int main(void) {
    int a, b;
    printf("Two ints: ");
    scanf("%d %d", &a, &b);

    printf("GCD(%d, %d) = %d\n", a, b, gcd(a, b));
    return 0;
}
Exercise 2

Problem 2 (hw02.c)

Goal: Write `int max(const int *a, int n)` and demonstrate.

Requirements
  • Filename: hw02.c
Toggle solution
SOLUTION
#include <stdio.h>

int find_max_index(const int *arr, int n) {
    int idx = 0;
    for (int i = 1; i < n; i++)
        if (arr[i] > arr[idx]) idx = i;
    return idx;
}

int main(void) {
    int arr[] = {3, 7, 2, 8, 5, 8, 1};
    int n = (int)(sizeof(arr) / sizeof(arr[0]));

    int idx = find_max_index(arr, n);
    printf("max %d is at index %d.\n", arr[idx], idx);
    return 0;
}
Exercise 3

Problem 3 (hw03.c)

Goal: Write `double mean(const int *a, int n)` and `double stddev(const int *a, int n, double m)`.

Requirements
  • Filename: hw03.c
Toggle solution
SOLUTION
#include <stdio.h>

void printBinary(unsigned int n) {
    if (n > 1) printBinary(n / 2);
    putchar('0' + (n % 2));
}

int main(void) {
    unsigned int n;
    printf("Positive int: ");
    scanf("%u", &n);

    printBinary(n);
    putchar('\n');
    return 0;
}
Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub ↗