Step 1 of 5 · Reading · ~4 min
Learn
Functions and Pointers
Functions
By the end of this lesson you can write a C function with several parameters, make it return a value on every path, and call it from main as many times as you need. You will also know the one rule behind all C argument passing: the function gets a copy.
The shape of a function
int cube(int k) {
return k * k * k;
}
int main(void) {
printf("%d\n", cube(3)); /* 27 */
printf("%d\n", cube(-2)); /* -8 */
return 0;
}
A definition is the return type (int), the name (cube), the parameter list (int k, each parameter with its own type) and a body. return hands a value back to the caller and ends the function at once. void in the return slot means "returns nothing"; void inside the parentheses, as in int main(void), means "takes no arguments".
Several exits, one per case
A function may contain more than one return. The first one reached wins, and nothing after it runs:
int sign(int n) {
if (n > 0) {
return 1;
}
if (n < 0) {
return -1;
}
return 0;
}
Trace sign(-4): -4 > 0 is false, skip. -4 < 0 is true, return -1, done. Trace sign(0): both tests are false, so control reaches the last line and returns 0.
That last line is the trap. Delete it and the code still compiles, but sign(0) now falls off the end of a non-void function. The caller receives whatever happened to be left in a register: 0 on one run, 1 on another, something else on the grader. gcc -Wall warns "control reaches end of non-void function". Rule: every path through the body ends in a return.
Parameters match by position
int span(int from, int to) {
return to - from;
}
span(3, 10) /* 7 */
span(10, 3) /* -7 */
C never matches arguments to parameters by name. The first argument goes into the first parameter, the second into the second. Swap them at the call and you get a different, still plausible answer with no warning.
Declare before use
The compiler reads top to bottom, so it must see a function before the first call. Either define helpers above main, or put a prototype (the signature ending in ;, no body) above main and the full definition below it:
int cube(int k); /* prototype */
int main(void) { printf("%d\n", cube(4)); return 0; }
int cube(int k) { return k * k * k; }
Everything is a copy
void add_bonus(int points) {
points += 50; /* changes the local copy only */
}
int score = 20;
add_bonus(score);
printf("%d\n", score); /* 20, not 70 */
Parameters are private copies of the arguments. To get a result out, return it and assign it at the call: score = with_bonus(score);. Changing the caller's variable directly needs its address, which is the next lesson.
One function, many calls
A function you wrote once can be called as often as you like. This loop reads a count, then that many numbers, and classifies each with sign:
int count, t;
scanf("%d", &count);
for (int i = 0; i < count; i++) {
scanf("%d", &t);
printf("%d\n", sign(t));
}
Input 3 then 8 0 -1 prints 1, 0 and -1 on three lines. The logic lives in the function; reading and printing stay in main.
Common mistakes
- Guarding only one side. A range check that tests the lower limit but forgets the upper one lets a too-large value through unchanged:
150is printed where100was expected. - Returning the wrong limit. Handing back the upper limit for a value that was too small turns
-3into10instead of0. Trace one low and one high value before submitting. - No return on the last path. Values that are already in range fall off the end and come back as garbage or
0. - Printing inside the helper.
mainalready prints the returned value, so aprintfinside the function doubles every line.
Your exercise
Complete clamp(value, lo, hi): it gives back lo for a value below the range, hi for a value above it, and the value itself otherwise. The starter's main already reads the input, calls clamp once per number and prints each result. The most likely mistake is a path with no return, so trace a value that is already inside the range.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…