function

Benefits of making function

  • Very often in computer programs there is some code that must be executed multiple times in different places in the program.
  • It is also common to need the same code in multiple different programs.
  • Encapsulating frequently-used code into functions makes it easy to re-use the code in different places and/or different programs.
  • Separating code out into functions also allows the programmer to concentrate on different parts of the overall problem independently of the others.
    • In "top-down" programming a programmer first works on the overall algorithm of the problem, and just assumes that functions will be available to handle individual details.
    • Functions can then be concentrated on independently of the greater context in which they will be used.
  • Well-written functions should be general enough to be used in a wide range of contexts, not specific to a particular problem.
  • Functions can be stored in libraries for later re-use. Examples of functions we have used include log( ), sqrt( ), abs( ), cos( ), etc.

Syntax and Components

  • The general syntax of a function is as follows:
return_type function_name( arg_type argument, ... )  {
         local_variable_type  local_variables;
         executable  statement(s);
         return  return_value;
     }
  • Example:
int add( int a, int b ) {
         int sum;
         sum = a +  b;
         return  sum;
     }

Return Type

  • The "return type" indicates what kind of data this function will return.  In the example above,the function returns an int. 
  • Some languages differentiate between "subroutines", which do not return a value, and "functions", which do.  In C there are no subroutines, only functions, but functions are not required to return a value.  The correct way to indicate that a function does not return a value is to use the return type "void".  ( This is a way of explicitly saying that the function returns nothing. )
  • If no return type is given, the compiler will normally assume the function returns an int.  This can cause problems if the function does not in fact return an int.

Function Name

  • The function name is an identifier by which this function will be known, and obeys the same naming rules as applied to variable names ( Alphanumeric characters, beginning with alpha, maximum 31 significant characters, etc. )

Formal Parameter List

  • Following the function name are a pair of parentheses containing a list of the formal parameters, ( arguments ) which receive the data passed to the function.
  • The ANSI standard requires that the type of each formal parameter to be listed individually within the parentheses as shown in the above example.  Even if several parameters are of the same type, each must have its type given explicitly.
  • If a function takes no parameters, the parameters may be left empty.  The compiler will not perform any type checking on function calls in this case.  A better approach is to include the keyword "void" within the parentheses, to explicitly state that the function takes no parameters.

Function Body

  • The body of the function is enclosed within curly {} braces, just as the "main" function with which we have been dealing so far, and contains the instructions that will be executed when this function is called.
  • The function body starts by declaring all local variables, prior to any executable statements.
    • In C99 variables can be declared any time before they are used, but in general it is still best to declare all variables that will be used at the beginning of the function, or at the beginning of the block in which they are used for very local variables. ( See scope below. )
    • There are actually two schools of thought on this issue:
      1. Declaring all variables at the top of the function puts them all together, in one comprehensive list. If you print out the program, then all the variables will print on the same page, making a sort of "checklist" of variables to be taken care of.
      2. If you only work on the computer, and never from printouts, it can be difficult to continuously scroll back and forth between the variable declarations at the beginning of the function and the part of the program you are working on. Declaring the variables just before you use them keeps the declaration and use on the same screen without scrolling.
      3. ( As a compromise, you can declare the variables just before use while working on the program, and then move them all up to the top of the function after the program is running

The Return Statement

  • The return statement exits the called function and returns control back to the calling function. 
    • Once a return statement is executed, no further instructions within the function are executed.
  • A single return value ( of the appropriate type ) may be returned. 
    • Parentheses are allowed but not required around the return value. 
    • A function with a void return type will not have a return value after the return statement. 
  • More than one return statement may appear in a function, but only one will ever be executed by any given function call.
    • ( All returns other than the last need to be controlled by logic such as "if" blocks. )
  • If a function does not contain a return statement, most compilers will add one automatically at the end of the routine, and may generate a warning message.  The return value, if any, is undefined in this case. 
  • "main( )" is technically a function, and should return 0 upon successful completion, or a non-zero value otherwise.  This is ignored by many programmers, but some compilers will issue warning messages if main() does not contain a return statement.

Function Prototypes ( a.k.a. Function Declarations )

  • When the compiler processes a call to a function, it will check to see that the correct number and types of data items are being passed to the function, and will automatically generate type conversions as necessary.  This is known as type checking.
  • Type checking is only possible if the compiler already knows about the function, including what kind of data the function is expecting to receive.  Otherwise, the compiler has to make assumptions, which can lead to incorrect and erratic behavior if those assumptions are not correct.
  • One way of dealing with this situation is to make certain that all functions appear earlier in a file than any calls to them.  This works for simple cases, but can make large complex programs hard to follow, and does not work in the cases of ( mutually ) recursive functions and functions located in separate files or libraries.
  • A better approach is to use function prototypes.  This is a way of declaring to the compiler what data a function will require, without actually providing the function itself.
  • Examples: 
            int add( int a, int b );
            int  add( int, int );
  • Note that the function prototypes end with semicolons, indicating that this is not a function, but merely a prototype of a function to be provided elsewhere.
  • Note also that the variable names are not required in the function prototype.  They may be included for clarity if you wish, but the compiler will ignore them.  This also means that the variable names used in the function prototype do not need to match those used in the actual function itself.
  • For clarity it is generally good style to list all functions that will be used by prototypes at the beginning of the file. Then provide main( ) as the first full function definition, followed by each of the other functions in the order in which the prototypes are listed. ( I.e. the prototype list acts as a kind of table of contents for the actual function which appear after main. )
  • Function prototypes are often placed in separate header files, which are then included in the routines which need them.  For example, "math.h" includes the function prototypes for the C math functions sqrt( ) and cos( ). 
  • Exercise:  Write function prototypes for:
    1. A function which takes an int and a float, and returns a double.
      • Answer: double myfunction( int, float );
    2. A function which takes no arguments and returns no value.
      • Answer: void yourfunction( void );

    Operation

    Calling a Function

    • A function is called by using the function name, followed by a set of parentheses containing the data to be passed to the function.
    • The data passed to the function are referred to as the "actual" parameters.  The variables within the function which receive the passed data are referred to as the "formal" parameters.
    • The formal parameters are local variables, which exist during the execution of the function only, and are only known by the called function.  They are initialized when the function starts by copies of the data passed as actual parameters.  This mechanism, known as "pass by value", ensures that the called function can not directly change the values of the calling functions variables.  ( Exceptions to this will be discussed later. )
    • To call a function which takes no arguments, use an empty pair of parentheses.
    • Example:         total = add( 5, 3 );
    • VERY IMPORTANT:  It is crucial that the number and types of actual parameters passed match with the number and types of parameters expected by the functions formal parameter list. ( If the number of arguments matches but the data types do not, then the compiler MAY insert some type conversion code if the correct data types are known, but it is safer not to rely on this. )
    • NOTE CAREFULLY: The actual parameters passed by the calling program and the formal parameters used to receive the values in the called function will often have the same variable names. However it is very important to recognize that they are totally different independent variables ( because they exist in different scopes, see below ), whether they happen to have the same name or not.
      • Example: In the code below, the variables x, y, z, and x again in main are used to initialize the variables x, z, b, and c in the function. The fact that x and z appear in both main and the function is irrelevant - They are independent variables with independent values.
              void func( double x, double z, double b, double c );
              
              int main( void ) {
              
                  double x( 1.0 ), y( 2.0 ), z( 3.0 );
                  
                  func( x, y, z, x );
      • The call to the function above initializes the function parameters equivalently to the following assignment statements:
        • x in func = x in main
        • z in func = y in main
        • b in func = z in main
        • c in func = x in main

0 Comments:

Post a Comment