CHRIS GERBER: A function is a series of steps within a
larger program, which is usually intended to be called
multiple times and from multiple other locations in
the program.
When creating a C function, one of the requirements is to
specify a return value type.
The simplest case is a situation where the calling
code is not concerned with the result of the function.
This might be the case when we are printing data to the
user's display, as with printf.
In this case, we can declare a return value
to be of type void.
Using void simply tells the compiler that no
value will be returned.
Let's see what this looks like.
>> Let's say that we have a function called say_hello that
takes one argument.
We'll pass it a person's name and it will display a greeting
on the screen.
The name will be of type char*.
And we'll specify that as the argument.
My application doesn't need to know what was printed or if it
was printed.
So the return value will be of type void.
This function may print to the screen with a command like
printf("Hello, %s\n
", name);.
The greeting will be displayed and control will be passed
back to the calling code.
One thing to note is that when the return value type is void,
you do not need to include a return
statement in the function.
If you choose to include one, don't include a return value
as an argument.
>> In some cases, it makes sense to return a
value from a function.
Let's say that we were writing a function called add_floats.
We'll pass it two arguments, both floats,
called first and second.
And it will tell us what the sum of those floats is.
We know that if we add two floats together, the result
will be a float.
Given that, we choose a return type of float.
This function will perform this calculation and return
the values in a statement like return
first + second;.
When control is passed back to the calling code, the
resulting value is now available to that code.
We can store this value like so: float result =
add_floats(3.14, 1.62
);.
Result in this case would now contain the value 4.76.
>> As a reminder, floating point values are imprecise.
So if this was a financial calculation, using dollars and
cents, we may want to consider a precise data type such as
int and perform the calculation in pennies.
>> Another case where we would want to return a value from a
function is when we want to know if a function was
successful.
If it was not successful, we may also want to know what type of
error occurred.
Let's say that we're trying to open a file on disk to count
the number of characters in it.
If the file can't be opened, we want to be able to stop and
tell the user about the problem.
>> We'll call our function count_file_chars and it will
take one argument.
We'll pass in the name of the file using a
char* called filename.
This function might look something like this.
In this example, we would expect the count returned to
be 0 or more.
This leaves us the negative integers to
use as sentinel values.
A sentinel value is simply a special value that is not
legitimate data but does convey information.
Here, if I return a -1 to the calling code, I am
actually sending the message that an error occurred while
trying to access the file.
I could then check that return value to determine if my
function call was successful.
If the number was 0 or greater, I would know the
number of characters in the file.
If, however, the number was less than 0, I could simply
print that a problem had occurred.
One trade-off to consider is that by reserving all the
negative values as sentinel values, assuming this is a
32-bit integer, I have essentially taken away around
2 billion possible return values.
>> Return value types are one of the most important elements of
function calls.
Hopefully this short overview has helped you think about
three key types: void, result values, and sentinel values,
and when each of the three might be
appropriate in your code.
Thanks for watching.