Introduction
A void function does a job. A function with a return type answers a question.
int addUp(int a, int b) {
return a + b;
}
int total = addUp(3, 4); // total is 7
The void has been replaced by int, which is a promise: this function hands back a whole number. return is where it keeps that promise.
That one change is what let the last lesson's rollDice() stop reaching out and modifying a global. A function that takes what it needs and hands back an answer depends on nothing outside itself — so it can be tested on its own, and dropped into another sketch tomorrow unchanged.
return also ends the function immediately. Anything after it never runs. That is useful in its own right: check for the bad case first, return early, and the rest of the function can assume everything is fine.
Even a void function can use return; on its own to leave early.
What you will be able to do
By the end of this lesson you can:
- Write a function with a return type and use its answer.
- Say what
returndoes to the rest of the function. - Use an early
returnto handle a bad case first. - Use
return;in avoidfunction. - Explain why returning a value beats changing a global.
What you need
| Part | Type | Qty |
|---|---|---|
| Arduino UNO R3 | Microcontroller | 1 |
| USB A to B cable | Cable | 1 |
Basic
No wiring. Read everything in the Serial Monitor at 9600 baud.
A function that answers
int square(int n) {
return n * n;
}
void setup() {
Serial.begin(9600);
Serial.println(square(7)); // 49
int a = square(3);
int b = square(a); // 81 — the answer of one feeds the next
Serial.println(b);
}
void loop() {
}
The type before the name says what comes back. int square(...) returns an int.
The value can be printed, stored, or passed straight into something else. That is what makes these functions build on each other.
Any type
float average(int total, int count) {
return (float)total / count;
}
bool isHot(int temperature) {
return temperature > 30;
}
char grade(int mark) {
if (mark >= 80) return 'A';
if (mark >= 60) return 'B';
return 'F';
}
isHot() is worth a second look. It returns the result of the comparison — a bool — with no if at all. Then:
Challenges
Challenge 1
Three small answers.
Write and test:
int doubleIt(int n)— returns twice n.float toCelsius(float f)— returns(f - 32) * 5 / 9.bool isEven(int n)— returns true when n divides by 2.
Print doubleIt(21), toCelsius(98.6) and isEven(7).
Then use them together: print doubleIt(doubleIt(5)) and explain what happened.
Log in to ask for the answer.
Challenge 2
A grader.
Write char grade(int mark) returning:
| Mark | Grade |
|---|---|
| 80 and above | A |
| 60 to 79 | B |
| 40 to 59 | C |
| below 40 | F |
Use early returns — no else anywhere in the function.
Test it with 95, 80, 79, 60, 40, 39 and 0. The boundaries are the point.
Then remove the final return and see what the compiler says.
Log in to ask for the answer.
Challenge 3
Turn a void into an answer.
Here is a void function that reaches out to a global:
int result;
void addUp(int a, int b) {
result = a + b;
}
- Rewrite it as
int addUp(int a, int b)returning the answer. - Delete the global entirely.
- Print
addUp(2, 3) + addUp(4, 5).
That last line is impossible with the first version. Explain in one sentence why.
Extra challenge
Statistics as functions.
Take the array from ARD-PG-13:
int readings[10] = {23, 45, 12, 67, 34, 89, 21, 56, 78, 43};
Write four functions, each taking the array and its length:
int total(int arr[], int len)float average(int arr[], int len)int biggest(int arr[], int len)int countAbove(int arr[], int len, int threshold)
Note the parameter shape int arr[] — that is how an array is passed.
Then setup() should be four printed lines, calling them.
Watch out: sizeof(arr) inside those functions will not give you 10. That is why len is a parameter.
Think about it: average() needs the total. Should it call total() rather than adding the values again? Try it both ways. Which would you rather change if the definition of the total ever altered?
Log in to ask for the answer.