C Crash Course, Part 1: Methods, Parameters and Return Values
This is part one of a C programming mini crash-course.
So you’ve learned some C programming and at some point encountered methods, parameters and return values. But why do we need those?
As you probably know, the entry point of all the software we write is
main:
#include <stdio.h>
int main(int argc, char** argv){ printf("Hello world\n"); return 0;}But as soon as we write any software that really does anything (except
print “hello world”), main quickly evolves to contain lots of lines of
code and becomes hard to read and understand.
As an example, let’s assume we want to write software for a system that can control the temperature in a room. We need to read the temperature sensor and turn on a heater if it is too cold in the room (too cold is defined as less than 30 degrees for now).
My main program becomes:
int main(int argc, char** argv){ // loop forever { // read temperature
// if temperature is too low, raise temperature }}Note that I have only written the comments. This is the way I always write code: comments first, to plan what the code will do.
The next step is to implement the software. I could implement it all in
main(), but I’ve just argued why that is not a good idea. We need
methods.
int main(int argc, char** argv){ // loop forever while (true) {
// read temperature readTemperature();
// if temperature is too low, turn on heater if (temperature < 30) { turnOnHeater(); } } return 0;}Now I have introduced the two methods readTemperature() and
turnOnHeater(). The code won’t compile, because the methods don’t exist
yet. Let’s implement them:
#include <stdint.h>void readTemperature(){ // do something to read the temperature // from a sensor}
void turnOnHeater(){ // do something to turn on a heater}
int main(int argc, char** argv){ uint8_t temperature = 0;
// loop forever while (true) { // read temperature readTemperature();
// if temperature is too low, turn on heater if (temperature < 30) { turnOnHeater(); } } return 0;}Note that the main() method is still very easy to read. Actually,
because good names were chosen for the methods, most of the comments in
main() are no longer needed — they can be removed and the code still
makes sense.
The code compiles now, but we have a problem: the temperature variable
is never updated. We need return values.
#include <stdint.h>
int8_t readTemperature(){ // do something to read the temperature // from a sensor
return 25; // just a hardcoded value for now}
void turnOnHeater(){ // do something to turn on a heater}
int main(int argc, char** argv){ uint8_t temperature = 0; while (true) // loop forever { temperature = readTemperature();
if (temperature < 30) { turnOnHeater(); } } return 0;}Now the readTemperature() method is no longer marked void. void
has been replaced with int8_t, which means the method will return an
8-bit signed integer. This means that when the method is invoked, the
calling code can use that return value — as seen in main(), where the
temperature variable gets assigned the return value from
readTemperature().
The code to read from a sensor isn’t implemented yet, so readTemperature()
just returns a hardcoded value of 25.
In the current implementation, the heater will heat at maximum whenever it’s turned on. That’s probably not a good idea, so let’s give it 3 settings, where 1 is low, 2 is medium, and 3 is max. Which setting to use will be determined by the difference between the actual temperature and the desired temperature.
| Desired temperature – actual temperature | Heater setting |
|---|---|
| >0 | 1 |
| >5 | 2 |
| >10 | 3 |
We need some way to tell the heater which setting to use. We need parameters.
#include <stdint.h>
int8_t readTemperature(){ // do something to read the temperature // from a sensor
return 25; // just a hardcoded value for now}
void turnOnHeater(int8_t setting){ // do something to turn on a heater}
int main(int argc, char** argv){ uint8_t temperature = 0; while (true) // loop forever { temperature = readTemperature();
if ((30 - temperature) > 10) { turnOnHeater(3); } else if ((30 - temperature) > 5) { turnOnHeater(2); } else if ((30 - temperature) > 0) { turnOnHeater(1); } } return 0;}Note that the turnOnHeater() method has changed. Its complete signature
is now:
void turnOnHeater(int8_t setting)
This means that code which invokes the method is required to provide an 8-bit integer as a parameter to the method. Inside the method, this parameter is called setting.
Right now we don’t actually have a heater, so let’s just print the
setting to the console — that can be done with printf. Right now the
readTemperature() method always returns the same temperature. We can
make the program a bit more interesting if we let the method return a
random value in a given range.
#include <stdint.h>#include <stdio.h>#include <stdlib.h>
int8_t readTemperature(){ // create a random temperature
uint32_t randValue = rand(); // generate random value uint8_t limitedValue = randValue % 15; // limit to 0-15
// the fake temperature will be between 18 and 32 uint8_t fakeTemperature = 18 + limitedValue;
return fakeTemperature;}
void turnOnHeater(int8_t setting){ // do something to turn on a heater printf("Heater on: %d\r\n", setting);}
int main(int argc, char** argv){ uint8_t temperature = 0; while (true) // loop forever { temperature = readTemperature();
if ((30 - temperature) > 10) { turnOnHeater(3); } else if ((30 - temperature) > 5) { turnOnHeater(2); } else if ((30 - temperature) > 0) { turnOnHeater(1); } } return 0;}The printf() method formats a string and prints it to the console.
printf has many formatting options; the documentation for them can be
found here.
Exercises
Section titled “Exercises”- Make
turnOnHeater()print something different on the console, depending on the heater setting. - Right now, the heater will never be turned off. Extend the program so the heater is turned off when the temperature is 30 degrees or above.
- The desired temperature is hardcoded to 30 degrees. In a real
application, the desired temperature would probably be input from a
sensor or entered on a user interface. Add a
getDesiredTemperature()method to the program and use the return value from that method when the heater setting is calculated inmain(). You can let the method return a hardcoded value for now.