            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.   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
        not minimize the value of functions,  it merely  illustrates


                                  Page 31









            Chapter 5 - Functions, variables, and prototypes


        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
        called  function.   We  could  have  modified  the  variable


                                  Page 32









            Chapter 5 - Functions, variables, and prototypes


        "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
        assigned  the value 4 prior to this call, "y" would then  be
        set to 16 as a result of this line of code.


                                  Page 33









            Chapter 5 - Functions, variables, and prototypes



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

             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


                                  Page 34









            Chapter 5 - Functions, variables, and prototypes


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

             There  will  be times that you will have a need  for  a
        function   to   return  a  pointer  as  a  result  of   some
        calculation.  There is a way to define a function so that it
        does  just that.   We haven't studied pointers yet,  but  we
        will soon.  This is just a short preview of things to come.

                             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.



                                  Page 35









            Chapter 5 - Functions, variables, and prototypes


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


                                  Page 36









            Chapter 5 - Functions, variables, and prototypes


        variable  private  and  not accessible to use in  any  other
        file.  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  if possible in order to speed up the execution  of
        the program.  Turbo C allows you to use 2 register variables
        and will ignore additional requests if you request more than
        2.

             Turbo C allows you to use register variables for  short
        int and int types along with their unsigned counterparts. It
        also  allows  you  to  use register  storage  for  two  byte
        pointers which we will study in about 3 chapters.

                        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.



                                  Page 37









            Chapter 5 - Functions, variables, and prototypes


                            WHAT IS PROTOTYPING?

             A  prototype  is a "model" of the real thing  and  when
        programming  in  Turbo C, 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  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 Turbo  C  at
        this  point to see how well it works.  In the "Option"  menu
        select  "Compiler", then "Errors", followed by "Less  common
        errors",  then  turn  on  "F:  Call  to  function  with   no
        prototype" by hitting the "F" key.  The program SCOPE.C will
        not produce any warnings, but RECURSON.C which is next  will
        result in some warning messages.

             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 and, when you  return  to
        the  Integrated  Environment,  observe  that  there  are  no
        warning messages.





                                  Page 38









            Chapter 5 - Functions, variables, and prototypes


                         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 Turbo C compiler writer for  all  of
        the  functions that are included with your compiler.  A  few
        minutes  spent  studying your Turbo C Reference  Guide  will
        give you an insight in where the prototypes are defined  for
        each of the functions.

             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
        the  Turbo  C  compiler on your own.   The  entire  Turbo  C
        Reference Guide is devoted to defining functions.   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 it  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 will return to DOS.



                                  Page 39









            Chapter 5 - Functions, variables, and prototypes


             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
        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  left   the
        prototype  checking on from the last program you  will  find
        several  "warnings"  in the message window when  you  return
        to  the  Integrated  Environment.  Study  these  for  a  few
        minutes.  One of the suggested exercises at the end of  this



                                  Page 40









            Chapter 5 - Functions, variables, and prototypes


        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
        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
        on, and observe the results.

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

             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.



                                  Page 41









            Chapter 5 - Functions, variables, and prototypes


             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.

        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
             the Turbo C compiler will allow it.

        3.   Add  prototyping  to the program  named  RECURSON.C  to
             eliminate the warnings.

































                                  Page 42
