Why Functions
Everything so far has lived inside main. That works until a program does more than one thing, and then three problems arrive at once: the same block of code gets copied into three places, main grows past what anyone can hold in their head, and there is no way to name what a chunk of code is for.
A function fixes all three. It gives a block of code a name, its own local variables, a list of inputs, and a single value to hand back.
square is written once and called three times, including once on its own result. You have already been calling functions - printf is one, and so is main.
Anatomy of a Function
returnType name(parameterList) {
// body
return value;
}
Four parts:
- Return type - the type of the value the function hands back.
int,double,char, a pointer type, orvoidfor "nothing". - Name - follows the same rules as a variable name, and should say what the function does or produces.
- Parameter list - the inputs, each with its own type, separated by commas.
(void)means it takes none. - Body - the statements, in braces, ending with a
returnunless the return type isvoid.
Note pi() still needs the empty parentheses at the call site - that is what makes it a call rather than a mention of the name. And printBanner(20); is a statement on its own, because it produces no value to use.
Write (void), not (), for a function with no parameters. In C those two mean different things, and () is the loose one - more on that shortly.
Calling and Returning
A call transfers control into the function, runs its body, and comes back with a value that replaces the call in the surrounding expression.
return does two things at once: it supplies the value and it ends the function on the spot. Anything after a return on the same path never runs, which is what makes the early-return style in larger work - no else is needed, because reaching the last line already means a > b was false.
A function can have several return statements. It can only ever execute one of them per call.
void Functions
A function that exists for its effect rather than its value has the return type void: printing, updating something through a pointer, drawing.
Inside a void function, return; with no value exits early. return someValue; is a compile error there, and so is using the call in an expression - int x = printTable(7, 5); will not compile, which is the type system doing its job.
Decomposition: The Real Point
Functions are not mainly about avoiding repetition. They are about turning one long procedure into a few named steps, so that main reads like a description of the program rather than its implementation.
main is now four lines of output and one calculation. Each helper does one thing, has a name that says what that thing is, and can be tested on its own. Notice that the array's length travels as a second parameter: once an array is passed to a function the sizeof trick no longer works there, because the array decays to a pointer.
Three rules of thumb for splitting work into functions:
- One job per function. If the name needs an "and" in it, it is probably two functions.
- Take what you need, return what you produce. A function that reads global state is harder to reason about and impossible to test in isolation.
- Short enough to see at once. There is no magic line count, but a function that does not fit on a screen is usually hiding a smaller function inside it.
Functions Calling Functions
A function can call any function that has already been declared, including ones you wrote:
main calls report, which calls sumEvens, which calls isEven inside a loop. Each call gets its own fresh set of local variables, stacked on top of the caller's, and they are discarded when it returns.
The definitions above are in dependency order - isEven before sumEvens before report - because C requires a function to be declared before it is called. Call one that appears further down the file and the compiler complains about an implicit declaration. The general fix is a prototype near the top of the file, which lets you order definitions however you like. A function calling itself is legal and useful too; that is recursion.
main Is a Function
main is an ordinary function that the runtime calls for you. Its int return type is the program's exit status: 0 means success, nonzero means failure, and shell scripts and build tools read it.
int main(void) {
/* ... */
return 0;
}
Since C99, falling off the end of main without a return implicitly returns 0 - a special rule that applies to main only. Every other non-void function that ends without returning a value produces undefined behavior when the caller uses the result.
The other standard form is int main(int argc, char *argv[]), which receives command-line arguments. Both are correct; void main() is not, whatever old tutorials say.
Common Mistakes
- Forgetting
returnin a non-void function. The caller then reads a garbage value.gcc -Wallwarns. - Declaring a variable with the same name as a parameter inside the body. It shadows the parameter, and the assignment you meant to make to the input goes nowhere.
- Expecting a function to change its arguments. C passes everything by value, so a function receives copies.
void reset(int x) { x = 0; }changes nothing at the call site - the subject of the next page. - Omitting the parentheses in a call.
printBanner;is a legal expression that evaluates the function's address and discards it. It compiles, does nothing, and-Wallflags it. - Writing
()instead of(void). Legal, but it turns off argument checking in older C dialects.
Frequently Asked Questions
How do you declare a function in C?
Write the return type, the name, and a parenthesised parameter list, then the body in braces: int add(int a, int b) { return a + b; }. A function that takes nothing uses (void), and one that returns nothing has the return type void.
What does return do in a C function?
It ends the function immediately and hands a value back to the caller. The value's type must match the function's declared return type. In a void function you can write a bare return; to exit early, or leave it out and let the function end at the closing brace.
Why does main return an int in C?
The return value of main is the program's exit status, which the operating system and shell scripts can read. return 0; means success and any nonzero value means failure. Since C99, reaching the end of main without a return statement implicitly returns 0.
Can a C function return more than one value?
Not directly - return produces exactly one value. The usual workarounds are to return a struct containing several fields, or to pass pointers as parameters and have the function write its extra results through them.