Functions
Splitting programs into reusable pieces: declarations, scope, and recursion.
A function is a named, reusable block of code. Every C program already has at least one — main — and splitting logic into more of them is how you keep programs readable as they grow.
Defining and calling a function
1#include <stdio.h>23int square(int n) {4return n * n;5}67int main(void) {8int result = square(6);9printf("%d\n", result); // 3610return 0;11}
A function signature has three parts: a return type (int), a name (square), and a parameter list (int n). return both produces the function's result and immediately exits it.
Declarations vs. definitions
C reads top to bottom, so a function normally has to appear before it's used. When you need to call a function before its full definition — often because two functions call each other — declare it first with a prototype:
1int square(int n); // prototype: promises this function exists23int main(void) {4printf("%d\n", square(4)); // fine — the compiler trusts the prototype5return 0;6}78int square(int n) { // full definition, can come later in the file9return n * n;10}
void functions
A function that doesn't return a value uses void as its return type:
1void greet(const char *name) {2printf("Hello, %s!\n", name);3}
const here promises the function won't modify the string it's given — a useful signal to callers and to the compiler.
Parameters are passed by value
C copies each argument into the function's parameters. Changes made inside the function don't affect the caller's variable:
1void increment(int n) {2n = n + 1; // only changes the local copy3}45int main(void) {6int x = 5;7increment(x);8printf("%d\n", x); // still 59return 0;10}
scanf uses.Recursion
A function can call itself. Every recursive function needs a base case that stops the recursion, or it will call itself forever (and eventually crash with a stack overflow):
1int factorial(int n) {2if (n <= 1) return 1; // base case3return n * factorial(n - 1); // recursive case4}