Unit 9: Functions Deeper
Recursion, scope and sharing data.
Unit 9 of 11 in C programming for kids. Its 5 lessons are Functions That Call Themselves, Where Names Live, Passing Arrays, The String Toolkit and Function Master — below is everything each one explains, and a question or two from it to try.
Every sample on this page was compiled and run with gcc before it shipped, and prints exactly what it says it prints.
This unit opens with a fortnight’s trial of everything — no card needed — or with a family plan, bought in the iPhone app. The first two units of every track are free for ever. Try it in the app.
🪆 Functions That Call Themselves
A function may call itself
That is recursion. It needs a way to stop — the base case — and a step that gets closer to it.
C
#include <stdio.h>
void countdown(int n) {
if (n == 0) {
printf("Liftoff!\n");
return;
}
printf("%d\n", n);
countdown(n - 1);
}
int main() {
countdown(3);
return 0;
}
It prints
3 2 1 Liftoff!
Building the answer on the way back
Each call waits for the one inside it to finish, then uses that answer. factorial(4) is 4 times whatever factorial(3) works out to be.
C
#include <stdio.h>
int factorial(int n) {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
printf("%d\n", factorial(5));
return 0;
}
It prints
120
Try it yourself
What happens without a base case?
- It returns 0
- It calls itself for ever until the program runs out of room and crashes
- The compiler refuses
- It runs once
What does this print?
C
#include <stdio.h>
int total(int n) {
if (n == 0) {
return 0;
}
return n + total(n - 1);
}
int main() {
printf("%d\n", total(4));
return 0;
}
Answer them in the app
🏠 Where Names Live
A variable belongs to its braces
A name declared inside a function — or inside any { } — exists only there. When the braces close, it is gone. That is why two functions can both use i without ever getting confused.
C
#include <stdio.h>
void helper(void) {
int n = 99;
printf("inside: %d\n", n);
}
int main() {
int n = 1;
helper();
printf("outside: %d\n", n);
return 0;
}
It prints
inside: 99 outside: 1
Even a loop has its own
A variable declared in the for header belongs to the loop. After the loop it no longer exists — which is why a total has to be declared outside it.
C
#include <stdio.h>
int main() {
int total = 0;
for (int i = 1; i <= 3; i++) {
total = total + i;
}
printf("%d\n", total);
return 0;
}
It prints
6
A global belongs to everyone
A variable declared outside every function can be seen and changed by all of them. Handy, but risky — when anything can change it, working out what went wrong gets hard.
C
#include <stdio.h>
int score = 0;
void add_point(void) {
score = score + 1;
}
int main() {
add_point();
add_point();
printf("%d\n", score);
return 0;
}
It prints
2
Try it yourself
Why is passing a value in and returning it out usually better than a global?
- It is faster
- You can see everything the function touches from its own line — nothing changes behind your back
- Globals are not allowed
- It uses less memory
What does this print?
C
#include <stdio.h>
int count = 5;
void change(void) {
int count = 100;
count = count + 1;
}
int main() {
change();
printf("%d\n", count);
return 0;
}
Answer them in the app
📦 Passing Arrays
The array itself is never copied
Give an array to a function and only its *address* is handed over. So the function works on the original — change it there and the change is real.
C
#include <stdio.h>
void zero_first(int nums[]) {
nums[0] = 0;
}
int main() {
int scores[3] = {7, 8, 9};
zero_first(scores);
printf("%d %d\n", scores[0], scores[1]);
return 0;
}
It prints
0 8
Which is why the length must come too
Because only an address arrives, the function cannot tell how long the array is — sizeof inside it measures the pointer. Every C function that takes an array takes its length as well.
C
#include <stdio.h>
int total(int nums[], int length) {
int sum = 0;
for (int i = 0; i < length; i++) {
sum = sum + nums[i];
}
return sum;
}
int main() {
int scores[] = {3, 1, 4};
int length = sizeof(scores) / sizeof(scores[0]);
printf("%d\n", total(scores, length));
return 0;
}
It prints
8
A single value IS copied
This is the difference that catches everyone. An int parameter is a copy, so changing it changes nothing outside — but an array parameter is a shared address.
C
#include <stdio.h>
void change_number(int n) {
n = 99;
}
void change_array(int a[]) {
a[0] = 99;
}
int main() {
int n = 1;
int a[1] = {1};
change_number(n);
change_array(a);
printf("%d %d\n", n, a[0]);
return 0;
}
It prints
1 99
Try it yourself
Why can sizeof find the length in main but not inside the function?
- It can do both
- main has the real array; the function only has an address, and sizeof measures that address
- sizeof only works once
- The array is deleted
Answer it in the app
🧵 The String Toolkit
You cannot just assign a string
A C string is an array of characters, and one array cannot be assigned to another. strcpy copies the characters across, one at a time.
C
#include <stdio.h>
#include <string.h>
int main() {
char name[20];
strcpy(name, "Ada");
printf("%s\n", name);
printf("%d\n", (int)strlen(name));
return 0;
}
It prints
Ada 3
Joining two together
strcat sticks the second string onto the end of the first. The first has to be big enough to hold both — C will not check for you.
C
#include <stdio.h>
#include <string.h>
int main() {
char full[30];
strcpy(full, "Ada");
strcat(full, " Lovelace");
printf("%s\n", full);
printf("%d\n", (int)strlen(full));
return 0;
}
It prints
Ada Lovelace 12
Comparing needs a function too
== on strings compares *addresses*, not letters, so it is almost never what you want. strcmp returns 0 when they match — which reads backwards at first, so it is worth remembering as "no difference".
C
#include <stdio.h>
#include <string.h>
int main() {
char password[20];
strcpy(password, "let-me-in");
if (strcmp(password, "let-me-in") == 0) {
printf("Welcome!\n");
} else {
printf("Wrong\n");
}
return 0;
}
It prints
Welcome!
Less than zero means "comes first"
When they differ, strcmp tells you which comes first alphabetically — negative for the first, positive for the second. That is how you sort words in C.
C
#include <stdio.h>
#include <string.h>
int main() {
printf("%d\n", strcmp("apple", "banana") < 0);
printf("%d\n", strcmp("banana", "apple") < 0);
return 0;
}
It prints
1 0
Try it yourself
What does strcmp(a, b) == 0 mean?
- a is empty
- The two strings are exactly the same
- a comes first alphabetically
- They are different
Answer it in the app
🏆 Function Master
Try it yourself
What does this print?
C
#include <stdio.h>
int mystery(int n) {
if (n <= 0) {
return 0;
}
return n + mystery(n - 2);
}
int main() {
printf("%d\n", mystery(6));
return 0;
}
Answer it in the app