Functions






Like practically every programming language, C has many ways to break your code up into smaller chunks to make it both more manageable and easier to maintain. Functions are one of the two major ways to accomplish this, the other being modules (which we'll get to soon). Essentially, a function is just a segment. You've been using functions so far in every program you've written so far: the required function main(). Now, main() is a somewhat generic function. The other functions you write will probably have more specific purposes. In general, functions are sections of code that do something small and specific. Sometimes, these functions will be called multiple times from elsewhere in your program. Splitting your program up into functions also makes it easier to debug: by breaking the program into chunks, it's easier to tell exactly where your problems are occuring. Now lets see just how to define a function in C.

Function Prototypes

Before you can use a function, you must declare it, in much the same way as you must declare a variable before you use it. Functions differ, though, in that you must both declare and define them. The declarations are called function prototypes, and typically go before main(). As an example, let's make a function that adds two integers. The prototype would look like this:

int Add_2_Numbers(int num1, int num2);

Though it may not look like it, this is the same format as you have used in defining main(). The first part of the prototype, the int, is the return type of the function. You must specify what kind of data, if anything, the function will return when it is called. If you don't want the function to return anything, you can use the keyword void as the return type. This is in fact what you have been doing all along with main(), although in that case you can leave the void out. Next in the prototype comes the name of the function. Here, I've named it Add_2_Numbers. While that may seem clunky, it's always a good idea to give your functions (and variables) descriptive names. This way, I'll never forget what that function does. Finally, we have the arguments of the function, enclosed in parentheses and separated by commas. Each argument must specify its type and a name. A function can take as many arguments as you'd like. Finally, you must end the prototype line with a semicolon.

Function Definitions

Now that we've declared a function, we must define it. Function definitions typically go after the main program. The first line must be the same as the prototype, although without the semicolon; if it is at all different, you'll get compiler errors. In the definition of the function, we use curly braces instead of a semicolon to enclose the block of code, much like we do for loops. Here is the implementation of the Add_2_Numbers() function:

int Add_2_Numbers(int num1, int num2)
{
   return (num1 + num2);
}

Fairly simple, huh? The keyword return is used to tell the program what value to return from the function. Here, we're returning the value of the expression num1 + num2, which is an integer to match the declared return type. Since this function returns an integer, it can be used in any place you would expect to find an integer: on the right hand side of an assignment, in a printf(), or anywhere else you'd like.

Variables and Functions

There are two kinds of variables in C: global variables and local variables. Globals can be seen and be used by everything in the program. They are declared outside of any functions (including main()). There are many pitfalls associated with global variables, though. For one thing, since their values can be changed by any part of a program, if when debugging your program you find that the problem is that a global variable is being set to the wrong value, this assignment could have happened at any time in the program. For this reason, and many others, you should avoid using global variables unless it is absolutely necessary (such as to save the state of a module, which I'll talk more about later). Local variables, on the other hand, can only be seen by the function that declared them. Just as you declare variables at the top of main(), you can declare any number of variables you need at the top of any function. Remember, though, that any variables declared in a function prototype are already local to that function, and so don't need to be redeclared (and in fact can't be).

Since variables are local to their own functions, you can reuse names if you'd like. For example, say I had declared an integer variable in main() named i. Later in the program in a function, call it myfunc(), I can declare another integer variable called i without a problem, and there will be no interference from the earlier variable. When you declare a variable in a function, the program reserves memory for that variable. When the function ends, all the memory allocated for its variables is freed, and everything in the variables is erased.

One final word about variables in functions: with what you know now, you cannot return more than one value from a function. By the same token, any changes you make to a variable inside a function are discarded unless you return them. An example should clarify this:

/* Function Prototype */
int foo(int i, int j, int k);

/* Main Program */
main()
{
   int i, j, k;

   /* initalize the variables */
   i = 1;
   j = 2;
   k = 3;

   i = foo(i, k, j);
   printf("i is now %d, j is %d, and k is %d.\n", i, j, k);
}

/* Definition of foo() */
int foo(int i, int j, int k)
{
   i = j;
   k = 10;
   j = 9;
   return i;
}

So what is this program's output? When all is said and done, i is 3, j is 2, and k is 3. Not what you expected? First of all, notice that I switched the order of j and k when I called foo(). Since the three variables inside foo() are local, they are completely separate from the variables declared in main(), and the only interaction between them is that passing the variables from main() has the effect of initializing the variables in foo(). In this case, i is getting the value of what was k in main(). Also, note that the values of j and k did not change even though I changed their values in foo(). The reason for this is that for every kind of data type you've learned about so far, the program actually copies the information into a new space in memory while the function is being executed. Essentially, this means that when you alter something inside a function, all you're doing is working on a copy. You need to put information from the copy somewhere if you want to save it. We'll see things that don't act this way in a bit.



Back to Control Structures and Loops   On to More About Libraries
Back to the Outline