Functions

A function packages up a piece of logic under a name, so you can run it again without retyping it, and so main doesn't turn into one enormous wall of code.

Declaring and calling a function

A function's definition states its return type, its name, and the types of whatever it accepts:

C main.c
#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int main(void) {
    int sum = add(3, 4);
    printf("Sum: %d\n", sum);
    return 0;
}
Output
Sum: 7

int add(int a, int b) says: this function is named add, it returns an int, and it takes two int parameters, a and b. Inside main, add(3, 4) is a call — the values 3 and 4 get copied into a and b, the function body runs, and return a + b; sends 7 back to wherever the call happened.

Note: C passes arguments by value — a function gets its own private copies of whatever you hand it. Changes made to a parameter inside the function don't affect the original variable back in the caller. The Pointers lesson shows the workaround for when you actually need a function to modify something outside itself.

Functions that return nothing: void

Not every function needs to hand a value back. Use void as the return type for one that just performs an action:

C main.c
#include <stdio.h>

void greet(char name[]) {
    printf("Hello, %s!\n", name);
}

int main(void) {
    greet("Priya");
    greet("Sam");
    return 0;
}
Output
Hello, Priya!
Hello, Sam!

greet takes a parameter and prints something, but there's no return statement with a value — a bare return; (or reaching the end of the function) is enough, since there's nothing to hand back.

Function prototypes

C reads a file top to bottom, and by default a function has to be defined before anything that calls it. A prototype — the function's signature followed by a semicolon, with no body — lets you promise the compiler "this function exists, I'll show you the body later," so you can call it from code that comes earlier in the file:

C main.c
#include <stdio.h>

int square(int n);

int main(void) {
    printf("Square of 6 is %d\n", square(6));
    return 0;
}

int square(int n) {
    return n * n;
}
Output
Square of 6 is 36

Notice the third line, int square(int n); — same as the real function's first line, just with a semicolon instead of a body. That's enough for the compiler to check that square(6) inside main is being called correctly, even though the actual definition doesn't appear until after main.

Note: in practice, prototypes for functions shared across multiple files are usually collected in a header file (a .h file) and pulled in with #include — which is exactly what <stdio.h> is doing for printf. You're including a file full of prototypes, not the actual implementation.