
            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.   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.   It  begins  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  "index"  in  the parentheses  of  the  call  to
        "square".  We have seen that this program therefore 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
        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 within 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 "sum" equal  to
        zero because we will use it to accumulate a sum of  squares.
        Since  the  variable  "sum" is defined as  an  integer  type
        variable  prior to the main program,  it is available to  be
        used  in  any of the following functions.   It is  called  a
        "global" variable,  and it's scope is the entire program and
        all  functions.   More  will  be  said about  the  scope  of
        variables near the end of this chapter.  The next  statement
        outputs  a header message to the monitor.   Program  control
        then  returns  to  the  main  program  since  there  are  no
        additional statements to execute in this function.

             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


                                  Page 29









            Chapter 5 - Functions, variables, and prototypes


        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

             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++".  You should get used to seeing this, as  you
        will see it a lot in C programs.

             In the call to the function "square",  we have an added
        feature, namely the variable "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  "square",  we  find that another variable name  is
        enclosed in its parentheses,  namely 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, the
        line  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 "numsq" for use only within  the  function
        itself,  (more  about  that  later)  and  proceed  with  the
        required  calculations.   We set "numsq" equal to the square
        of  number,  then add numsq to the current total  stored  in
        "sum".   Remember  that "sum += numsq" is the same as "sum =
        sum + numsq" from the last lesson.   We print the number and
        its square, and return to the main program.

                  MORE ABOUT PASSING A VALUE TO A FUNCTION

             When we passed the value of "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


                                  Page 30









            Chapter 5 - Functions, variables, and prototypes


        called  function.   We  could  have  modified  the  variable
        "number" in any way we wished in the function "square",  and
        when we returned to the main program, "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 "ending".  This call simply calls
        the last function which has no local variables defined.   It
        prints out a message with the value of "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 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  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  "squ"  function
        taking along the value of "x" as a variable.  Looking  ahead
        to the function itself we find that the function prefers  to
        call  the variable "in" and it proceeds to square the  value
        of  "in" and call the result "square".  Finally, a new  kind
        of  a statement appears, 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 "y" is
        then  set  equal  to  that value.   If  "x"  were  therefore



                                  Page 31









            Chapter 5 - Functions, variables, and prototypes


        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 "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 which the function call is placed in the print
        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.

             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 return.  It begins by defining
        a global floating point variable 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 the 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 "sqr" near the center of the
        listing and you will see that the function name is  preceded
        by the name "float".   This is an indication to the compiler
        that  this  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".




                                  Page 32









            Chapter 5 - Functions, variables, and prototypes


             The next function,  namely "glsqr",  will also return a
        "float"  type  variable,  but it uses a global variable  for
        input.   It  also 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.

               THERE IS A BUG IN THE FIRST VERSION OF TURBO C

             When you run this program, if you are using version 1.0
        of  Turbo C, you will find that the function  named  "sqr()"
        will return a value of zero.  This is because it receives  a
        zero  from  the  calling program.  The  program  is  written
        correctly  but  the  compiler has a bug in it.   A  call  to
        Borland  resulted  in  a fix by simply  using  the  "modern"
        method  of  function definition rather  than  the  "classic"
        which has been used to this point.  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.   We
        will  return to this program and show how to fix it so  that
        it will work in spite of the bug.

                             SCOPE OF VARIABLES

             Load the next program,  SCOPE.C,  and display it for  a
        discussion  of the scope of variables in a program.   Ignore
        the 4 statements in lines 2 through 5 of this program for  a
        few moments, and we will discuss them later.

             The first variable defined is a global variable "count"
        which  is available to any function in the program since  it
        is defined before any of the functions.   In addition, 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  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.

             Return  to  the  main  program and  you  will  see  the
        variable  "index"  defined as an integer.   Ignore the  word
        "register" for the moment.   This variable is only available


                                  Page 33









            Chapter 5 - Functions, variables, and prototypes


        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,  namely  "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  "index"  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.   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 to a function to the  next
        call,  the  value of an automatic variable is not  preserved
        and must therefore be reinitialized.

                         WHAT ARE STATIC VARIABLES?

             An  additional variable type must be mentioned at  this
        point,  the "static" variable.  By putting the reserved word
        "static"  in  front  of  a  variable  declaration  within  a
        function,  the variable or variables in that declaration are
        static  variables  and will stay in existence from  call  to
        call  of  the  particular function.

             By  putting  the  same reserved word  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 implies that it is possible to refer to external


                                  Page 34









            Chapter 5 - Functions, variables, and prototypes


        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  if possible in order to speed up the execution  of
        the  program.  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.

                        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 program.   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 the real thing  and  when
        programming with a good up-to-date C compiler, you have  the


                                  Page 35









            Chapter 5 - Functions, variables, and prototypes


        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 should be released  late  in
        1987,   and  will  contain  prototyping  as  part   of   its
        recommended  standard.   Every  good C  compiler  will  have
        prototyping available, so you should learn to use it.

             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  "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.

             You should enable prototype checking with your compiler
        at this time, if it is available with your 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.

             Compile  and run 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.



                                  Page 36









            Chapter 5 - Functions, variables, and prototypes


             In addition,  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 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.

             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
        "index"  is  set to 8,  and is used as the argument  to  the
        function  "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 "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


                                  Page 37









            Chapter 5 - Functions, variables, and prototypes


        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  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.

             Compile and run this program.  If you compile this with
        prototype  checking  on  you will  find  several  "warnings"
        issued  during compilation.  Study these for a few  minutes.
        One of the suggested exercises at the end of this chapter is
        to modify this program to eliminate the prototype warnings.

                        ANOTHER EXAMPLE OF RECURSION

             The  program  named  BACKWARD.C is another  example  of
        recursion,  so load it and display 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


                                  Page 38









            Chapter 5 - Functions, variables, and prototypes


        names  themselves.   The  final  result  is  that  the  line
        containing   the   function  name  looks   more   like   the
        corresponding line in Pascal, Modula 2, or Ada.

             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.

                 HOW TO WORK AROUND THE TURBO C (v1.0) BUG

             If you are using Turbo C version 1.00, load and display
        the  program named FLOATSQ2.C which is an exact copy of  the
        program   FLOATSQ.C   which  we  considered   earlier   with
        prototyping added.  The return of the erroneous zeros is now
        repaired  and the correct values are returned.   Apparently,
        when  the  coders of Turbo C at Borland  were  testing  this
        compiler,  they used prototyping and never found  this  bug.
        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.  They can be included in line  12,
        but they are not required to be.

             Notice  also that the type of the variable  "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.












                                  Page 39









            Chapter 5 - Functions, variables, and prototypes


        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 program  named  RECURSON.C  to
             eliminate the warnings.









































                                  Page 40
