home *** CD-ROM | disk | FTP | other *** search
-
-
-
-
- Chapter 5
- FUNCTIONS, VARIABLES, AND PROTOTYPES
-
-
- OUR FIRST USER DEFINED FUNCTION
- ____________________________________________________________
-
- Load and examine the file SUMSQRES.C for an ==============
- example of a C program with functions. SUMSQRES.C
- Actually this is not the first function we ==============
- have encountered because the main program we
- have been using all along is technically a
- function, as is the printf() function. The printf() function
- is a library function that was supplied with your compiler.
-
- Notice the executable part of this program which begins in
- line 8 with a line that simply says "header();", which is the
- way to call any function. The parentheses are required
- because the C compiler uses them to determine that it is a
- function call and not simply a misplaced variable. When the
- program comes to this line of code, the function named
- header() is called, its statements are executed, and control
- returns to the statement following this call. Continuing on
- we come to a for loop which will be executed 7 times and which
- calls another function named square() each time through the
- loop, and finally a function named ending() will be called and
- executed. For the moment ignore the variable name index in
- the parentheses of the call to square. We have seen that this
- program calls a header, 7 square calls, and an ending. Now
- we need to define the functions.
-
-
- DEFINING THE FUNCTIONS
- ____________________________________________________________
-
- Following the main program you will see another program
- beginning in line 14 that follows all of the rules set forth
- so far for a main program except that it is named header().
- This is the function which is called from line 8 of the main
- program. Each of these statements are executed, and when they
- are all complete, control returns to the main program.
-
-
- The first statement sets the variable named sum equal to zero
- because we plan to use it to accumulate a sum of squares.
- Since the variable named sum is defined prior to the main
- program, it is available to be used in any of the following
- functions. It is called a global variable, and its scope is
- the entire program and all functions. It is also sometimes
- referred to as a file variable because it is available
- throughout the file. More will be said about the scope of
- variables near the end of this chapter. The statement in line
- 17 outputs a header message to the monitor. Program control
-
- Page 5-1
-
- Chapter 5 - Functions, Variables, & Prototypes
-
- then returns to the main program since there are no additional
- statements to execute in this function. Essentially, we drop
- out of the bottom of the function and return to the caller.
-
- It should be clear to you that the two executable lines from
- this function could be moved to the main program, replacing
- the header call, and the program would do exactly the same
- thing that it does as it is now written. This does not
- minimize the value of functions, it merely illustrates the
- operation of this simple function in a simple way. You will
- find functions to be very valuable in C programming.
-
-
- PASSING A VALUE TO A FUNCTION (CLASSIC METHOD)
- ____________________________________________________________
-
- Going back to the main program, and the for loop specifically,
- we find the new construct from the end of the last lesson used
- in the last part of the for loop, namely the index++ used in
- line 9. You should get familiar with this construct, as you
- will see it in a lot in C programs.
-
- In the call to the function named square(), we have an added
- feature, namely the variable name index within the
- parentheses. This is an indication to the compiler that when
- you go to the function, you wish to take along the value of
- index to use in the execution of that function. Looking ahead
- at the function named square(), we find that another variable
- name is enclosed in its parentheses, the variable number.
- This is the name we prefer to call the variable passed to the
- function when we are in the function. We can call it anything
- we wish as long as it follows the rules of naming an
- identifier. Since the function must know what type the
- variable is, it is defined following the function name but
- before the opening brace of the function itself. Thus, line
- 21 containing "int number;" tells the function that the value
- passed to it will be an integer type variable. With all of
- that out of the way, we now have the value of index from the
- main program passed to the function square(), but renamed
- number, and available for use within the function. This is
- the classic style of defining function variables and has been
- in use since C was originally defined. A newer method is
- gaining in popularity due to its many benefits and will be
- discussed later in this chapter.
-
- Following the opening brace of the function, we define another
- variable named numsq for use only within the function itself,
- (more about that later) and proceed with the required
- calculations. We set the variable named numsq equal to the
- square of the value of number, then add numsq to the current
- total stored in the variable named sum. Remember that "sum
- += numsq;" has the identical meaning as "sum = sum + numsq;"
- from the last lesson. We print the number and its square in
- line 27, and return to the main program.
-
- Page 5-2
-
- Chapter 5 - Functions, Variables, & Prototypes
-
-
- MORE ABOUT PASSING A VALUE TO A FUNCTION
- ____________________________________________________________
-
- When we passed the value of the variable named index to the
- function, a little more happened than meets the eye. We did
- not actually pass the value of index to the function, we
- actually passed a copy of the value. In this way the original
- value is protected from accidental corruption by a called
- function. We could have modified the variable named number
- in any way we wished in the function named square(), and when
- we returned to the main program, the variable named index
- would not have been modified. We thus protect the value of
- a variable in the main program from being accidentally
- corrupted, but we cannot return a value to the main program
- from a function using this technique. We will find a well
- defined method of returning values to the main program or to
- any calling function when we get to arrays and another method
- when we get to pointers. Until then the only way you will be
- able to communicate back to the calling function will be with
- global variables. We have already hinted at global variables
- above, and will discuss them in detail later in this chapter.
-
- Continuing in the main program, we come to the last function
- call, the call to the function named ending() in line 11.
- This line calls the last function which has no local variables
- defined. It prints out a message with the value of the
- variable sum contained in it to end the program. The program
- ends by returning to the main program and finding nothing else
- to do. Compile and run this program and observe the output.
-
-
- NOW TO CONFESS A LITTLE LIE
- ____________________________________________________________
-
- I told you a short time ago that the only way =============
- to get a value back to the main program was SQUARES.C
- through use of a global variable, but there =============
- is another way which we will discuss after
- you load and display the file named
- SQUARES.C. In this file we will see that it is simple to
- return a single value from a called function to the calling
- function. But once again, it is true that to return more than
- one value, we will need to study either arrays or pointers.
-
- In the main program, we define two integers and begin a for
- loop in line 6 which will be executed 8 times. The first
- statement of the for loop is "y = squ(x);", which is a new and
- rather strange looking construct. From past experience, we
- should have no trouble understanding that the squ(x) portion
- of the statement is a call to the function named squ() taking
- along the value of x as a variable. Looking ahead to line 15
- of the function itself, we find that the function prefers to
- call the input variable in, and it proceeds to square the
-
- Page 5-3
-
- Chapter 5 - Functions, Variables, & Prototypes
-
- value of in and call the result square. Finally, a new kind
- of a statement appears in line 21, the return statement. The
- value within the parentheses is assigned to the function
- itself and is returned as a usable value in the main program.
- Thus, the function call "squ(x)" is assigned the value of the
- square and returned to the main program such that the variable
- named y is then set equal to that value. If the variable
- named x were therefore assigned the value 4 prior to this
- call, y would then be set to 16 as a result of this line of
- code.
-
- Another way to think of this is to consider the grouping of
- characters squ(x) as another variable with a value that is the
- square of x, and this new variable can be used any place it
- is legal to use a variable of its type. The values of the
- variables x and y are then printed out.
-
- To illustrate that the grouping of squ(x) can be thought of
- as just another variable, another for loop is introduced in
- line 11 in which the function call is placed in the printf()
- statement rather than assigning it to a new variable.
-
- One last point must be made, the type of variable returned
- must be defined in order to make sense of the data, but the
- compiler will default the type to integer if none is
- specified. If any other type is desired, it must be
- explicitly defined. How to do this will be demonstrated in
- the next example program.
-
- Be sure to compile and run this program which also uses the
- classic method of defining function variables.
-
-
- FLOATING POINT FUNCTIONS
- ____________________________________________________________
-
- Load the program FLOATSQ.C for an example of =============
- a function with a floating point type of FLOATSQ.C
- return. It begins by defining a global =============
- floating point variable named z which we will
- use later. Then in the main part of the
- program, an integer is defined, followed by two floating point
- variables, and then by two strange looking definitions. The
- expressions sqr() and glsqr() look like function calls and
- they are. This is the proper way in C to define that a
- function will return a value that is not of type int, but of
- some other type, in this case float. This tells the compiler
- that when a value is returned from either of these two
- functions, it will be of type float. This is, once again, the
- classic method of defining functions.
-
- Now refer to the function named sqr() starting in line 22 and
- you will see that the function name is preceded by the keyword
- float. This is an indication to the compiler that this
-
- Page 5-4
-
- Chapter 5 - Functions, Variables, & Prototypes
-
- function will return a value of type float to any program that
- calls it. The function is now compatible with the call to it.
- The line following the function name contains float inval;,
- which indicates to the compiler that the variable passed to
- this function from the calling program will be of type float.
-
- The function named glsqr() beginning in line 31, will also
- return a float type variable, but it uses a global variable
- for input. It does the squaring right within the return
- statement and therefore has no need to define a separate
- variable to store the product.
-
- The overall structure of this program should pose no problem
- and will not be discussed in any further detail. As is
- customary with all example programs, compile and run this
- program.
-
-
- THE CLASSIC STYLE
- ____________________________________________________________
-
- The three programs we have studied in this chapter so far use
- the classic style of function definition. Although this style
- was the first defined for C, it is rapidly being replaced with
- the modern method of function definition because it does so
- much for you in detecting and flagging errors. As you read
- articles on C, you will see programs written in the classic
- style, so you need to be capable of reading them. It would
- be highly recommended, however, that you learn and use the
- modern method which will be covered shortly in this tutorial.
-
- The remainder of this tutorial will use the modern method as
- recommended and defined by the ANSI standard. If you have an
- older compiler, it may not work on some of these files and it
- will be up to you to modify the programs as needed to conform
- to the classic style.
-
-
- SCOPE OF VARIABLES
- ____________________________________________________________
-
- Load the next program, SCOPE.C, and display =============
- it for a discussion of the scope of variables SCOPE.C
- in a program. You can ignore the 4 =============
- statements in lines 2 through 5 of this
- program for a few moments. We will discuss
- them later.
-
- The first variable defined is a global variable named count
- which is available to any function in the program since it is
- defined before any of the functions. It is always available
- because it does not come and go as the program is executed.
- (That will make sense shortly.) Farther down in the program,
- another global variable named counter is defined in line 25
-
- Page 5-5
-
- Chapter 5 - Functions, Variables, & Prototypes
-
- which is also global but is not available to the main program
- since it is defined following the main program. A global
- variable is any variable that is defined outside of any
- function. Note that both of these variables are sometimes
- referred to as external variables because they are external
- to any functions, and they are sometimes called file
- variables.
-
- Return to the main program and you will see the variable named
- index defined as an integer in line 11. Ignore the word
- register for the moment. This variable is only available
- within the main program because that is where it is defined.
- In addition, it is an automatic variable, which means that it
- only comes into existence when the function in which it is
- contained is invoked, and ceases to exist when the function
- is finished. This really means nothing here because the main
- program is always in operation, even when it gives control to
- another function. Another integer is defined within the for
- braces named stuff. Any pairing of braces can contain a
- variable definition which will be valid and available only
- while the program is executing statements within those braces.
- The variable will be an automatic variable and will cease to
- exist when execution leaves the braces. This is convenient
- to use for a loop counter or some other very localized
- variable.
-
-
- MORE ON AUTOMATIC VARIABLES
- ____________________________________________________________
-
- Observe the function named head1() in line 26 which looks a
- little funny because of void being used twice. The purpose
- of the uses of the word void will be explained shortly. The
- function contains a variable named index, which has nothing
- to do with the variable named index in line 11 of the main
- program, except that both are automatic variables. When the
- program is not actually executing statements in this function,
- this variable named index does not even exist. When head1()
- is called, the variable is generated, and when head1()
- completes its task, the variable in head1() named index is
- eliminated completely from existence. (The automatic variable
- is stored on the stack. This topic will be covered later.)
- Keep in mind however that this does not affect the variable
- of the same name in the main program, since it is a completely
- separate entity.
-
- Automatic variables therefore, are automatically generated and
- disposed of when needed. The important thing to remember is
- that from one call of a function to the next call, the value
- of an automatic variable is not preserved and must therefore
- be reinitialized.
-
-
-
-
- Page 5-6
-
- Chapter 5 - Functions, Variables, & Prototypes
-
- WHAT ARE STATIC VARIABLES?
- ____________________________________________________________
-
- An additional variable type must be mentioned at this point,
- the static variable. By putting the keyword static in front
- of a variable definition within a function, the variable or
- variables in that definition are static variables and will
- stay in existence from call to call of the particular
- function.
-
- By putting the same keyword in front of an external variable,
- one outside of any function, it makes the variable private and
- not accessible to use in any other file. (This is a
- completely different use of the same keyword.) This implies
- that it is possible to refer to external variables in other
- separately compiled files, and that is true. Examples of this
- usage will be given in chapter 14 of this tutorial.
-
-
- USING THE SAME NAME AGAIN
- ____________________________________________________________
-
- Refer to the function named head2(). It contains another
- definition of the variable named count. Even though count has
- already been defined as a global variable, it is perfectly all
- right to reuse the name in this function. It is a completely
- new variable that has nothing to do with the global variable
- of the same name, and causes the global variable to be
- unavailable in this function. This allows you to write
- programs using existing functions without worrying about what
- names were used for variables in the functions because there
- can be no conflict. You only need to worry about the
- variables that interface with the functions.
-
-
- WHAT IS A REGISTER VARIABLE?
- ____________________________________________________________
-
- Now to fulfill a promise made earlier about what a register
- variable is. A computer can keep data in a register or in
- memory. A register is much faster in operation than memory
- but there are very few registers available for the programmer
- to use. If there are certain variables that are used
- extensively in a program, you can designate that those
- variables are to be stored in a register in order to speed up
- the execution of the program. The method of doing this is
- illustrated in line 11. Your compiler probably allows you to
- use one or more register variables and will ignore additional
- requests if you request more than are available. The
- documentation for your compiler will list how many registers
- are available with your compiler. It will also inform you of
- what types of variables can be stored in a register. If your
- compiler does not allow the use of register variables, the
- register request will simply be ignored.
-
- Page 5-7
-
- Chapter 5 - Functions, Variables, & Prototypes
-
-
- WHERE DO I DEFINE VARIABLES?
- ____________________________________________________________
-
- Now for a refinement on a general rule stated earlier. When
- you have variables brought to a function as arguments to the
- function, and you are using the classic style of programming,
- they are defined immediately after the function name and prior
- to the opening brace for the executable statements. Other
- variables used in the function are defined at the beginning
- of the function, immediately following the opening brace of
- the function, and before any executable statements.
-
-
- WHAT IS PROTOTYPING?
- ____________________________________________________________
-
- A prototype is a model of a real thing and when programming
- with a good up-to-date C compiler, you have the ability to
- define a model of each function for the compiler. The
- compiler can then use the model to check each of your calls
- to the function and determine if you have used the correct
- number of arguments in the function call and if they are of
- the correct type. By using prototypes, you let the compiler
- do some additional error checking for you. The ANSI standard
- for C contains prototyping as part of its recommended
- standard. Every good C compiler will have prototyping
- available, so you should learn to use it. Much more will be
- said about prototyping throughout the remainder of this
- tutorial.
-
- Returning to lines 3, 4, and 5 in SCOPE.C, we have the
- prototypes for the three functions contained within the
- program. The first void in each line tells the compiler that
- these particular functions do not return a value, so that the
- compiler would flag the statement index = head1(); as an error
- because nothing is returned to assign to the variable named
- index. The word void within the parentheses tells the
- compiler that this function requires no parameters and if a
- variable were included, it would be an error and the compiler
- would issue a warning message. If you wrote the statement
- head1(index);, it would be a error. This allows you to use
- type checking when programming in C in much the same manner
- that it is used in Pascal, Modula-2, or Ada, although the type
- checking in C is very weak.
-
- Note the addition of the word void in line 9. This is an
- indication to the system that we do not plan to return a value
- to the operating system when we terminate operation of this
- program. The main program also can return a value in the same
- manner as any other function.
-
- You should enable prototype checking at this time, if it is
- available with your compiler. Check your documentation for
-
- Page 5-8
-
- Chapter 5 - Functions, Variables, & Prototypes
-
- the details of how to do it. Prototyping will be used
- throughout the remainder of this tutorial. If your compiler
- does not support prototyping and the modern method of function
- definition, you will have to modify the remaining example
- programs. A much better solution would be to purchase a
- better compiler.
-
- Line 2 of SCOPE.C tells the system to go to the include files
- and get the file named STDIO.H which contains the prototypes
- for the standard input and output functions so they can be
- checked for proper variable types. Don't worry about the
- include yet, it will be covered in detail later in this
- tutorial. Be sure to compile and execute this program.
-
-
- STANDARD FUNCTION LIBRARIES
- ____________________________________________________________
-
- Every compiler comes with some standard predefined functions
- which are available for your use. These are mostly
- input/output functions, character and string manipulation
- functions, and math functions. We will cover most of these
- in subsequent chapters. Prototypes are defined for you by the
- writer of your compiler for all of the functions that are
- included with your compiler. A few minutes spent studying
- your reference guide will give you an insight in where the
- prototypes are defined for each of the functions.
-
- Most compilers have additional functions predefined that are
- not standard but allow the programmer to get the most out of
- his particular computer. In the case of the IBM-PC and
- compatibles, most of these functions allow the programmer to
- use the BIOS services available in the operating system, or
- to write directly to the video monitor or to any place in
- memory. These will not be covered in any detail as you will
- be able to study these unique aspects of your compiler on your
- own. Many of these kinds of functions are used in the example
- programs in chapter 14.
-
-
-
- WHAT IS RECURSION?
- ____________________________________________________________
-
- Recursion is another of those programming ==============
- techniques that seem very intimidating the RECURSON.C
- first time you come across it, but if you ==============
- will load and display the example program
- named RECURSON.C, we will take all of the
- mystery out of it. This is probably the simplest recursive
- program that it is possible to write and it is therefore a
- stupid program in actual practice, but for purposes of
- illustration, it is excellent.
-
-
- Page 5-9
-
- Chapter 5 - Functions, Variables, & Prototypes
-
- Recursion is nothing more than a function that calls itself.
- It is therefore in a loop which must have a way of
- terminating. In the program on your monitor, the variable
- named index is set to 8 in line 9, and is used as the argument
- to the function named count_dn(). The function simply
- decrements the variable, prints it out in a message, and if
- the variable is not zero, it calls itself, where it decrements
- the variable again, prints it, etc. etc. etc. Finally, the
- variable will reach zero, and the function will not call
- itself again. Instead, it will return to the prior time it
- called itself, and return again, until finally it will return
- to the main program and from there return to DOS.
-
- For purposes of understanding you can think of it as having
- 8 copies of the function named count_dn() available and it
- simply called all of them one at a time, keeping track of
- which copy it was in at any given time. That is not what
- actually happened, but it is a reasonable illustration for you
- to begin understanding what it was really doing.
-
-
- WHAT DID IT DO?
- ____________________________________________________________
-
- A better explanation of what actually happened is in order.
- When you called the function from itself, it stored all of the
- variables and all of the internal flags it needs to complete
- the function in a block somewhere. The next time it called
- itself, it did the same thing, creating and storing another
- block of everything it needed to complete that function call.
- It continued making these blocks and storing them away until
- it reached the last function when it started retrieving the
- blocks of data, and using them to complete each function call.
- The blocks were stored on an internal part of the computer
- called the stack. This is a part of memory carefully
- organized to store data just as described above. It is beyond
- the scope of this tutorial to describe the stack in detail,
- but it would be good for your programming experience to read
- some material describing the stack. A stack is used in nearly
- all modern computers for internal housekeeping chores.
-
- In using recursion, you may desire to write a program with
- indirect recursion as opposed to the direct recursion
- described above. Indirect recursion would be when a function
- A calls the function B, which in turn calls A, etc. This is
- entirely permissible, the system will take care of putting the
- necessary things on the stack and retrieving them when needed
- again. There is no reason why you could not have three
- functions calling each other in a circle, or four, or five,
- etc. The C compiler will take care of all of the details for
- you.
-
- The thing you must remember about recursion is that at some
- point, something must go to zero, or reach some predefined
-
- Page 5-10
-
- Chapter 5 - Functions, Variables, & Prototypes
-
- point to terminate the loop. If not, you will have an
- infinite loop, and the stack will fill up and overflow, giving
- you an error and stopping the program rather abruptly.
-
- Be sure to compile and run this program.
-
-
- ANOTHER EXAMPLE OF RECURSION
- ____________________________________________________________
-
- The program named BACKWARD.C is another ==============
- example of recursion, so load it and display BACKWARD.C
- it on your screen. This program is similar ==============
- to the last one except that it uses a
- character array. Each successive call to the
- function named forward_and_backwards() causes one character
- of the message to be printed. Additionally, each time the
- function ends, one of the characters is printed again, this
- time backwards as the string of recursive function calls is
- retraced.
-
- This program uses the modern method of function definition and
- includes full prototype definitions. The modern method of
- function definition moves the types of the variables into the
- parentheses along with the variable names themselves. The
- final result is that the line containing the function
- definition looks more like the corresponding line in Pascal,
- Modula-2, or Ada. The prototype in line 5 is simply a copy
- of the function header in line 18 followed by a semicolon.
- The designers of C even allow you to include a variable name
- along with each type. The name is ignored by the compiler but
- including the name in the prototype could give you a good idea
- of how the variable is used, acting like a comment.
-
- Don't worry about the character array defined in line 9 or the
- other new material presented here. After you complete chapter
- 7 of this tutorial, this program will make sense. It was felt
- that introducing a second example of recursion was important
- so this file is included here.
-
- Compile and run this program with prototype checking enabled
- and observe the results.
-
-
- IF YOU CAN'T USE PROTOTYPING WITH YOUR COMPILER
- ____________________________________________________________
-
- If your compiler does not support prototyping remove line 5
- from BACKWARD.C and replace line 18 with the following lines;
-
- forward_and_backwards(line_of_char, index)
- char line_of_char[];
- int index;
-
-
- Page 5-11
-
- Chapter 5 - Functions, Variables, & Prototypes
-
- Load and display the program named FLOATSQ2.C =============
- which is an exact copy of the program FLOATSQ2.C
- FLOATSQ.C which we considered earlier with =============
- prototyping added. The use of prototyping is
- a good practice for all C programmers to get
- into.
-
- Several things should be mentioned about this program. First,
- the word float at the beginning of lines 27 and 35 indicate
- to the compiler that these functions are functions that return
- float type values. Also, since the prototypes are given
- before main, the functions are not required to be identified
- in line 12 as they were in line 7 of FLOATSQ.C earlier in this
- chapter.
-
- Notice also that the type of the variable named inval is
- included within the parentheses in line 27. It would be very
- educational for you to modify this program so that you
- included a call to sqr() with a variable of type int within
- the parentheses to see what kind of a warning you would get.
- Do the same thing in the program without prototype checking,
- FLOATSQ.C.
-
-
- PROGRAMMING EXERCISES
- ____________________________________________________________
-
- 1. Rewrite TEMPCONV.C, from an earlier chapter, and move
- the temperature calculation to a function.
-
- 2. Write a program that writes your name on the monitor 10
- times by calling a function to do the writing. Move the
- called function ahead of the main function to see if your
- C compiler will allow it.
-
- 3. Add prototyping to the programs named SUMSQRES.C and
- SQUARES.C, and change the function definitions to the
- modern method.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 5-12