05B All about Functions Part 2

This is part 2 of Lesson 5: All About Functions. I've copied Part 1 down at
the bottom of today's lesson for your convenience. Part 1 covers function
prototypes and definitions, main function odds and ends, and using gcc -Wall to
find errors when you compile your C programs.

Today we're going to play with functions some more, and learn about return
values, calling functions, and types of functions. The general form of a C
function looks like this:

return_type function_name (argument_data_type arg1, argument_data_type
arg2)
{
statement 1;
statement 2;
howevermanymore statements;
}

The return type is whatever C data type you want to use. Every function in a
program must have a unique name. If there is no return value you can use
"void" for your return type. If there are no arguments then you should enter
"void", because as we learned in Part 1 the empty parentheses means an unknown
number of arguments. It is always best to be explicit, so we want to use
"void" to indicate that there are zero arguments.

Functions are called from other functions, and perform specific tasks. If you
find that a function you are writing is getting fat and unwieldy, it might be a
sign to re-think what you're trying to make it do. Functions make it possible
to write nice modular programs that are easier to understand and modify.

You know how we have been using "return 0;" to end our functions? Where is
that value returning to? It's returned to the calling function. Return values
vary according to what we want our programs to do; they are used to indicate
success or failure, or they return a value to the calling function for further
operations.

C functions can be written five different ways:

1--No arguments or return values
2--Arguments and no return values
3--Arguments and return values
4--No arguments and return values
5--Return multiple values

Our very first example C program in this course had no arguments or return
values:

=======================

#include

int main (void)
{
printf( "Hello, and welcome to the Beginning C Course!\n" );
return 0;
}

=======================

Yes, this has been modified for correctness :) This is the simplest possible
function, using only main and no other functions. We can modify this so that
main calls a second function to do the same thing:

=======================

#include

void printmessage (void);

int main (void)
{
printmessage();
return 0;
}

void printmessage (void)
{
printf( "Hello, and welcome to the Beginning C Course!\n" );
}

========================

Now we have a function with no arguments or return value, printmessage, and
its calling function, main. Note how it has a proper function prototype and
declaration. Note that the function prototype ends in a semi-colon, while the
declaration does not.

A function with arguments and no return value looks like this:

========================

#include

void multiplynumbers (int, int);

int main (void)
{
multiplynumbers(10,11);
return 0;
}

void multiplynumbers (int a, int b)
{
int total;
total = a * b;
printf ( "%d times %d equals %d.\n",a,b,total);
}

=========================

Because it accepts no user input, you have to change the two numbers where
main calls multiplynumbers(10,11) and recompile to perform a different
calculation. You could call the multiplynumbers function several times, like
this:

multiplynumbers(10,11);
multiplynumbers(12,13);
multiplynumbers(14,15);

A function with arguments and return values looks like this:

==========================

#include

int addnumbers (int, int);

int main (void)
{
int c = addnumbers(25, 35);
int d = addnumbers(10, 20);
printf( "The variable c equals %d, and d equals %d\n",c,d);
printf( "Add c plus d and the total is %d\n",(c+d));

return 0;
}

int addnumbers (int a, int b)
{
return (a + b);
}

============================

This demonstrates how a return value can be used in multiple operations.

This is a good place to stop and review these examples until you are sure you
understand what is happening in each one. If you want to jump ahead, our next
lesson will cover the other two types of functions, and then take a dive into
local, static, and global variables.

===========================

HOMEWORK

Take any of these examples and modify them to accept user input, just like we
did in our previous lessons. Put as much functionality as possible into
separate functions and then call them from main.

If there are any gurus wishing for a bit of a challenge, give us some examples
of using functions efficiently and correctly.

What is the difference between:

void functionname (void)

and

int functionname (void)

Why is it OK to use 'void functionname (void)' for ordinary functions, but not
OK to use 'void main (void)' ?

Thank you and I'll be looking for your homework this week!

==================================
==================================
==================================

C Programming For Absolute Beginners, Lesson 5: All About Functions (part 1)

The discussion this past week has been wonderful, with fun digressions, good
homeworks, a great long tangent on binary, and a nice coding style howto by
Jacinta Richardson. If you haven't had time to follow along, maybe take a few
minutes to skim it because there is a lot of good stuff.

Today we are going to learn about functions. Functions are fundamental to all
programming, so we need to know all about them. Printf and scanf are
functions. They are also called routines. Programming languages are cram-full
of built-in functions, and of course when we write our own programs we write
our own functions. main is a function, a special required function in every C
program. Remember our initial discussions about the different ways to declare
main:

main ()
int main ()
void main (void)
int main (void)

'main ()' is the wrong way to declare main. Don't use it. I know, I used it in
our first lesson. Under the C89 standard, 'main ()' is acceptable. But not
under C99, which says we must use 'int main (void)' or 'int main ( int argc,
char *argv[] )'.
Please refer to C
Programming Resource Center
to read the C99 standard and get other useful
information. Section 5.1.2.2.1 Program startup says:

"The function called at startup is named main. The implementation declares no
prototype for this function. It shall be defined with a return type of int and
with no parameters:

int main (void)

or with two parameters (referred to here as argc and argv, though any names
may be used, as they are local to the function in which they are declared):

int main (int argc, char *argv[]) "

A common misconception is that the empty parentheses mean zero arguments. But
it really means an unknown number of arguments, which is quite different. So
what arguments are we talking about? This means command-line options for our
programs. This is jumping ahead a little, but we might as well get this sorted
now. Because someday we will write programs that take command-line arguments,
so instead of plain old commands like

$ books

we'll have fancier programs with command options:

$ books --cooloption1 --cooloption2

So the short story is I'm going to follow the C99 standard. And to think that
when I started this I expected I wouldn't have to pay attention to the
different standards :)

void main(void) is against all C standards. You'll see it in howto books. They
are wrong. Don't use it.

======= Function Prototypes and Definitions ========

Now let's talk about function prototypes and definitions. Function prototypes
describe your functions; they tell the compiler basic information about your
function such as what its return type, its name, its parameters, and its
types. Function definitions are your actual functions. This simple example
shows what this all means:

=======================================

//timex, a simple multiplication
//program demonstrating function
//prototypes and definitions

#include

int timex ( int, int );

int main(void)
{
int a = 0;
int b = 0;

printf( "Please type in two numbers no larger than 100, separated by a
space, to multiply: " );
scanf( "%d", &a );
scanf( "%d", &b );
printf( "The product of your two numbers is %d\n", timex( a, b ) );
return 0;
}

int timex (int a, int b)
{
return a * b;
}

==========================================

Compile this program with the --Wall option, which turns on all warnings so
the compiler will tell you about all errors, even non-fatal errors. As this
example shows, I send my executables to my ~/bin directory:

$ gcc -Wall -o ~/bin/timex timex.c

Now run the new program:

$ timex
Please type in two numbers no larger than 100, separated by a space, to
multiply: 55
44
The product of your two numbers is 2420

'int timex ( int, int );' is the function prototype. If you comment this out
it will compile with a warning:

$ gcc -Wall -o ~/bin/timex2 timex2.c
timex2.c: In function ‘main’:
timex2.c:17:3: warning: implicit declaration of function ‘timex’ [-Wimplicit-
function-declaration]

man gcc lists all the warnings flags that Wall supports. You can probably guess
what Wimplicit-function-declaration means, and man gcc tells you:

"Give a warning whenever a function is used before being declared."

You can include variable names in your function prototype:

int timex ( int a, int b );

But leaving them out lets you rename your variables as you need to. This is
the function definition:

int timex (int a, int b)
{
return a * b;
}

A great advantage of always using a function prototype is your compiler will
find errors such as wrong data types or wrong number of variables. Try changing
the function prototype to this:

int timex ( int, int, int );

This should generate a flurry of error messages:

$ gcc -Wall -o ~/bin/timex2 timex2.c
timex2.c: In function ‘main’:
timex2.c:17:3: error: too few arguments to function ‘timex’
timex2.c:7:5: note: declared here
timex2.c: At top level:
timex2.c:21:5: error: conflicting types for ‘timex’
timex2.c:7:5: note: previous declaration of ‘timex’ was here

Or try the wrong data type:

char timex ( int, int );

$ gcc -Wall -o ~/bin/timex2 timex2.c
timex2.c:21:5: error: conflicting types for ‘timex’
timex2.c:7:6: note: previous declaration of ‘timex’ was here