Functions: The Basics
Named, reusable codeA function is a named block of code. You write it once and call it whenever you need it — main is a function too, and so is printf. In the lab below you watch the program jump into a function and back, see every call get its own frame on the call stack, and find out why the compiler wants a prototype.
- Definewrite the code once
- Callrun it as often as you like
- returnsends a result back
Ready
Keyboard: ← → step · Space play / pause · R reset · Esc exit classroom mode
The ideas behind the lab
Exactly what you watched happen, in plain steps.
The three places a function appears
A function is written once (the definition), announced to the compiler before it is used (the prototype), and run whenever you write its name with brackets (the call). The definition has a head — return type, name, parameters — and a body in { }. A program can have as many functions as you like, but exactly one main.
int square(int x); // 1. prototype — "this function exists"
int main(void)
{
int s = square(5); // 2. call — run it, use the result
printf("%d
", s); // prints 25
return 0;
}
int square(int x) // 3. definition — head …
{
return x * x; // … and body
}
| Part | Example | Meaning |
|---|---|---|
| Return type | int | The type of the value sent back (void = nothing comes back) |
| Name | square | Follows the identifier rules; describe what it does |
| Parameter list | (int x) | Variables that receive the values sent in; (void) = none |
| Body | { return x * x; } | The statements that run on every call |
| Prototype | int square(int x); | The head + ; — written before the first call |
| Call | square(5) | Runs the function; its value replaces the call |
Why functions?
- Write once, use many times — no copy-and-paste of the same code.
- Split a big problem into small, named steps that are easy to read.
- Test and fix each piece on its own.
- A fix inside the function fixes every place that calls it.
- You already use them: main, printf, scanf are all functions.
What happens on a call
- The arguments are worked out first: square(a + 1) sends one value.
- C remembers where to come back to, then jumps into the function.
- A new frame is put on the call stack for the parameters and local variables.
- return value; (or the closing }) ends the function; the frame is removed.
- Back in the caller, the call is replaced by the returned value.
void, return and prototypes
- void line(void) — returns nothing and takes nothing.
- A void function may use return; on its own to leave early.
- A non-void function must return a value of its type on every path.
- The compiler reads top to bottom: a function must be declared before it is called.
- Either define it above main, or put its prototype above main (the usual style).
A prototype, a void function and a function with a result
Every line, explained.
#include <stdio.h>
int max(int a, int b);
Prototype: main may now call max, although it is defined below.
void greet(void)
Defined above main, so no prototype is needed.
{
printf("Welcome!\n");
}
The end of a void function — back to the caller.
int main(void)
The program starts here.
{
greet();
Prints Welcome!
int m = max(7, 12);
max returns 12, so m = 12.
printf("max = %d\n", m);
Prints max = 12
printf("%d\n", max(m, 20));
A call can be an argument: prints 20.
return 0;
}
int max(int a, int b)
The definition: the same head as the prototype.
{
if (a > b)
return a;
return ends the function at once …
return b;
… so this line runs only when a > b is false.
}
Spot the bug
Mistakes almost every beginner makes — and how to fix them.
Calling before declaring
int main(void) { printf("%d", add(2, 3)); }
int add(int a, int b) { return a + b; }
int add(int a, int b); // prototype first
int main(void) { printf("%d", add(2, 3)); }
int add(int a, int b) { return a + b; }
The compiler reads from the top. Without a prototype it does not know add yet: "implicit declaration of function".
Forgetting the brackets
greet; // does nothing
greet(); // calls the function
Without ( ) the name only refers to the function; nothing runs. Most compilers warn "statement with no effect".
Missing return in a non-void function
int square(int x)
{
int r = x * x;
}
int square(int x)
{
return x * x;
}
Without return the caller gets a garbage value. Every path of an int function must return an int.
A semicolon after the definition head
int square(int x);
{
return x * x;
}
int square(int x)
{
return x * x;
}
With ; the head is only a prototype, and the { } block that follows is outside any function — a compile error.
Using the result of a void function
int n = greet(); // greet is void
greet(); // just call it
A void function returns nothing, so there is no value to store: "void value not ignored as it ought to be".
Check your understanding
Answer each question — you will see the explanation straight away.
Where does every C program start running?
main is always the starting point, wherever it is in the file.
What does the prototype int add(int a, int b); tell the compiler?
A prototype is the head with a semicolon — a declaration, no code.
int sq(int x) { return x * x; } — what does sq(3) + sq(4) give?
9 + 16 = 25. Each call is replaced by its returned value.
What does void mean in void greet(void)?
The first void: nothing comes back. The second: nothing goes in.
A function is called 3 times. How many times was its code written?
That is the whole point: write once, call as often as you like.
Functions: The Basics quiz
Test yourself: 10 questions, 70% to pass. Create a free account to take the quiz, save your progress and work towards the certificate.