Skip to content Skip to sidebar Skip to footer

In C How Do I End a Function but Then Call It Again

Examples:
          int add together( int a, int b );         int  add( int, int );
Practice:  Write role 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.
    • Respond: void yourfunction( void );

Performance

Calling a Function

  • A role is called by using the office name, followed by a set of parentheses containing the information to be passed to the function.
  • The information passed to the function are referred to as the "actual" parameters.  The variables within the function which receive the passed data are referred to equally 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 role.  They are initialized when the part starts past copies of the data passed as actual parameters.  This mechanism, known every bit "pass past value", ensures that the called function can not directly modify 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.
  • Case:         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, so the compiler MAY insert some blazon conversion lawmaking if the correct information types are known, merely it is safer non 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 volition ofttimes have the same variable names. Nevertheless it is very of import to recognize that they are totally different independent variables ( because they exist in different scopes , encounter beneath ), whether they happen to accept the same proper noun or not.
    • Instance: In the code beneath, the variables x, y, z, and ten 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 chief( void ) {                      double ten( 1.0 ), y( 2.0 ), z( 3.0 );                          func( x, y, z, x );
    • The call to the role above initializes the part parameters equivalently to the following assignment statements:
      • ten in func = ten in primary
      • z in func = y in main
      • b in func = z in chief
      • c in func = x in principal

Returning from a Function

  • A function may return a single value past means of the return statement.
  • Whatsoever variable changes made inside a part are local to that function.  A calling function'south variables are not affected by the actions of a called function.  ( When using the normal pass-past-value passing mechanism for not-arrays. Meet too the section on alternate passing mechanisms below. )
  • The calling function may choose to ignore the value returned by the called role.  For example, both printf and scanf return values which are usually ignored.
  • The value returned by a role may be used in a more circuitous expression, or it may be assigned to a variable.
  • Annotation carefully that in the sample program shown beneath, information technology is the consignment statement which changes the value of y in the main program, not the function.

Sample Plan Calling a Role

          int add_two( int 10 ); // Adds 2 to its statement and returns the result          main() { // <----------------------------------------------------------- int main( void )                      int y = 5;                          cout << "Before calling any part, y = " << y << endl;                          add_two( y );                          cout <<  "Later on calling the function once, y = " << y << endl;                          y = add_two( y );                          "Afterward calling the function twice, y = " << y << endl;                          return 0;                      } // main                  int add_two( int x ) { // <---------------------------------------- int add_two( int )              cout <<  "In office, 10 inverse from " <<  ten;                          x += 2;                          cout <<  " to " <<  ten << endl;                          return x;                      } // add_two        
Output:
          Before calling any office, y = 5         In function, x changed from five to seven         After calling the function one time, y = five         In function, 10 changed from v to seven         After calling the function twice, y = 7

Information Passing Mechanisms

Pass By Value

  • Ordinary data types ( ints, floats, doubles, chars, etc ) are passed past value in C/C++, which means that only the numerical value is passed to the part, and used to initialize the values of the functions formal parameters.
  • Nether the pass-by-value mechanism, the parameter variables within a role receive a copy of the variables ( data ) passed to them.
  • Any changes fabricated to the variables within a office are local to that function only, and do not touch on the variables in chief ( or whatsoever other function called the current function. ) This is true whether the variables take the same name in both functions or whether the names are different.

Passing Arrays and/or Array Elements

  • When i element of an assortment is passed to a office, it is passed in the same manner equally the type of information contained in the array. ( I.e. pass-past-value for basic types. )
  • Nonetheless when the entire assortment is passed, it is effectively passed past reference. ( Really past pointer/address, to be explained completely in the section on pointer variables. )
  • See "Passing Arrays to Functions" beneath.

( Pass by Pointer / Address )

  • Pass by arrow / accost is another type of information passing that will be covered later under the section on pointer variables.
  • ( It is often mistakenly termed laissez passer-by-reference in some C textbooks, considering the actual pass-by-reference passing machinery is merely bachelor in C++. )
  • Pass by pointer / address requires use of the address operator ( & ) and the pointer dereference operator ( * ), to exist covered later.

( Pass past Reference )

  • C++ introduced a new passing machinery, pass by reference , that is not bachelor in ordinary C, and volition non be discussed further in these notes.

Passing Arrays to Functions

  • Recall that ordinary data types ( ints, floats, doubles, etc. ) are passed to functions by value , in which the part receives a copy and all changes are local.
  • If an individual element of an array is passed to a function, it is passed co-ordinate to its underlying data type.
    • So if nums was declared as a 1-dimensional array of ints, then passing nums[ i ] to a function would carry the exact way every bit passing whatsoever other int, i.e. pass-by-value.
  • When an unabridged array is passed to a function, all the same, it is effectively passed by reference .
    • ( Information technology is actually passed by arrow/address, to be covered later, merely effectively it is pass-past-reference. )
    • The net upshot, is that when an entire assortment is passed to a function, and the function changes variables stored in that array, information technology does affect the information in the calling role'southward array.
    • Because arrays are passed by reference, in that location is by and large no demand for a function to "return" an assortment. - It only needs to fill in an array provided by the calling function. ( It is possible for functions to return arrays merely it requires the apply of pointers and addresses, and frequently dynamic retentiveness allocation, none of which we are set up for nevertheless. )
    • In order to forestall the function from changing the array values, the array parameter can exist modified with the keyword const.
      • E.g. "void printArray( const int data[ ], int nValues );"
  • When an entire array is passed to a function, the size of the array is commonly passed as an additional statement.
  • For a one dimensional array, the function'southward formal parameter list does non demand to specify the dimension of the array.  If such a dimension is provided, the compiler volition ignore it.
  • For a multi-dimensional array, all dimensions except the first must exist provided in a functions formal parameter list.  The first dimension is optional, and volition be ignored by the compiler.
  • [ Advanced: A partially qualified multi-dimensional array may be passed to a function, and will exist treated every bit an array of lower dimension.  For case, a unmarried row of a 2 dimensional array may be passed to a role which is expecting a one dimensional assortment.  ( Question:  Why is it possible to pass a row this fashion, but not a column? ) ]
  • Examples: Annotation the use of arrays and functions in the following sample programme.  Note that in the calculation of max4, we take passed a 2 dimensional assortment containing two rows of three elements as if information technology were a unmarried dimensional array of 6 elements.  This is cheating, simply it happens to piece of work because of the way that the rows of a multidimensional array are stored.
            /* Program Illustrating the use of Arrays and Functions */                  #include <stdlib.h>         #include <stdio.h>                  // Finds max in the assortment         double maxArray( const bladder numbers[ ], int arraySize );                   int main( void ) {                      double array1[ ] = { ten.0, 20.0, 100.0, 0.001 };             double array2[ 2 ][ 3 ] = { { 5.0, 10.0, 20.0 },                                         { 8.0, fifteen.0, 42.0 } };                          int sizes[ two ] = { 4, 3 };             double max1, max2, max3, max4, max5;                          max1 = maxArray( array1, 4 );             max2 = maxArray( array1, sizes[ 0 ] );             max3 = maxArray( array2[ ane ], 3 );            // Advanced            max4 = maxArray( array2[ 0 ], six );            // Very Advanced            max5 = maxArray( array1, -4 ); // Generates an error - returns 0.0;                         printf( "Maximums are %f, %f, %f, %f, and %f\north", max1, max2, max3, max4, max5 );             return 0;                      }                  double maxArray( const double numbers[ ], int arraySize ) {                      /* Function to find the maximum in an assortment of doubles                Note the utilise of the keyword "const" to preclude changing array data */                          int i;             double max;              if( arraySize <= 0 ) {                 return 0.0;             }                                     max = numbers[ 0 ];                          for( i = 1; i < arraySize; i++ )                 max = ( numbers[ i ] > max ) ? numbers[ i ] : max;                              return max;                      }
  • New: In C99 it is possible to declare arrays using variable dimensions, providing the variable has a ( positive integer ) value at the time the announcement is made. It turns out that this carries over to the annunciation of arrays in function parameters every bit well, which tin be peculiarly useful for multi-dimensional arrays.
  • For instance, in the prototype:
int arrayFunction( int nRows, int nCols, double ten[ nRows ],                     double y[ nRows ][ nCols ] );

the variable dimension on 10 is informative to the human merely not necessary for the figurer, since nosotros could have declared information technology as x[ ]. However the nCols dimension on y is very useful, because otherwise the office would have to be written for arrays with pre-determined row sizes, and now we can write a part that volition piece of work for arrays with any row length.

Using Arrays to Return Multiple Values from Functions

  • Based on what we have learned so far, functions tin simply return a single value, using the "return" machinery.
  • One mode around that limitation is to pass an array to the function, and to allow the function fill up in the array.
    • The size of the assortment could range from a unmarried element to as many values every bit you desire the function to return.
    • The difficulty is that all the assortment elements must exist the same type, and do not get dissever names.
    • For instance, some of the earlier code could be improved to render an error lawmaking every bit well equally a consequence:
    • The maxarray function shown above tin can at present be improved as shown below. Programs using the improved version of maxArray should check the value of errorCode[ 0 ] before using the results.
  • Eventually we will learn how to get around this limitation using pointer / accost argument passing, and/or structs.
    • ( Global variables, discussed below, tin can besides technically get around this limitation, only there are very good reasons for avoiding global variables at all times unless absolutely necessary. )
  • Improved maxarray code:
            double maxArray( const double numbers[ ], int arraySize, int errorCode[ ] ) {                      /* Function to find the maximum in an assortment of doubles                Note the use of the keyword "const" to forbid irresolute array information */                          int i;             double max;              if( arraySize <= 0 ) {                 errorCode[ 0 ] = -ane;  // Errors plant in input.  Results invalid.                 return 0.0;             }              errorCode[ 0 ] = 0;  // No errors in input                                     max = numbers[ 0 ];                          for( i = i; i < arraySize; i++ )                 max = ( numbers[ i ] > max ) ? numbers[ i ] : max;                              return max;                      }          

Exercises

Write the post-obit functions:

  • double average( const double x[ ], int nValues );
    • Calculates the average of the values in ten.
    • nValues is how many elements to calculate
    • Function should return 0.0 if errors are encountered
  • double dot( const double x[ ], const double y[ ], int nValues );
    • Calculates the dot product of x and y.
    • nValues is how many elements to summate
    • Function should render 0.0 if errors are encountered
  • int calcSins( const double x[ ], double sinX[ ], int nValues );
    • Calculates the sin of each element of x, and stores the results in sinX.
    • nValues is how many elements to calculate
    • The return value is the actual number of values calculated. Information technology should exist equal to nValues if all goes well, or another value ( e.chiliad. zero ) if there is a trouble.

Recursion

  • Whatsoever function in C may telephone call any other function, including itself!
  • When a function calls itself, it is called recursion.
  • It is besides possible for a fix of functions to be circularly recursive, in which a function does not call itself direct, just does so indirectly through some other function(s). ( East.g. function A calls part B which calls office C which calls part A. )
  • A very important issue when writing recursive functions is that in that location exist a defined stopping condition that will stop the recursion and forbid information technology from calling itself forever in an infinitely recursive loop, and that there be a guarantee that once the function is chosen, it will somewhen reach that stopping status.
  • The classic example of recursion is the calculation of factorials.
    • The definition of the factorial of X, denoted as X! , is the product of X * ( X - i ) * ( 10 - 2 ) * . . . * 1.
    • X! tin can likewise exist defined recursively as:
      • 10! = ane for all Ten less than or equal to 1
      • X! = X * ( X - i )! for all X greater than one
    • This can exist programmed equally:
                    long int factorial( int Ten ) {          	if( X <= one )             	return one;              return 10 * factorial( X - 1 );         }

Graphic symbol Strings as Arrays of Characters

  • The traditional method for handling graphic symbol strings in C is to use an array of characters.
  • A null byte ( character constant zero, '\0' ) is used every bit a terminator signal to mark the stop of the cord.
  • Ordinary quoted strings ( "Please enter a number > " ) are stored as null-terminated arrays of characters.
  • The cord library contains a number of functions for dealing with traditional arrays of characters.
    • ( #include <string.h> )

Variable Telescopic

  • Variable scope refers to the range ( the scope ) in which a variable is defined and in which information technology exists.
  • There are iv variable scopes: ordinary local variables, function parameters, global variables, and very local variables.

    Ordinary Local Variables

    • Most of the variables that nosotros have used so far are ordinary local variables.
    • Ordinary local variables are alleged inside of a part, and outside of any braced blocks such as while or for loops.
    • The scope of these variables ( the range in which they exist and are valid ) is from the point of their announcement to the finish of the part.
    • Equally a general rule, all ordinary variables are commonly alleged at the very beginning of a role.
      • This was required in traditional C, simply is merely a programming way in C99.
      • Programmers who piece of work from printouts, and/or who have all-encompassing programming experience in C, tend to ascertain all their variables at the beginning of each function. This has the advantage, especially when working from printouts, of listing all variables in 1 identify, equally a sort of comprehensive inventory or checklist.
      • Programmers who work by and large or exclusively on the screen, particularly those who learned to program originally in C++ and not C, may prefer to declare their variables as close to where they are first used as possible. This has the reward of keeping variable declarations and their apply on the same screen, or at least within a short altitude of each other. At that place is also some argument for improving compiler optimization operation and for avoiding conflicts with other variables having the same names. ( Encounter "very local variables" and "variable eclipsing" below. )
      • For this class you lot may use either manner that yous wish, provided you are consistent.
    • Ordinary local variables are non initialized automatically. They must be initialized by the developer, or else they will start out with unknown random values. ( Possibly zeros in some cases, but you can't count on that. )

    Role Parameters

    • Function parameters have the same scope as ordinary local variables.
    • The only difference is that function parameters become initialized with the values passed to them past the calling function.

    Global Variables

    • Global variables are declared outside of whatever role, ordinarily at the very first of the file.
    • The telescopic of global variables is from the point of annunciation down to the end of the file.
      • ( Global variables can be made available to functions in other files as well, but that is beyond the scope of these notes. )
    • Global variables are accessible to all functions within a file ( beyond the betoken of announcement ), without having to exist passed.
    • Global variables introduce many opportunities for very hard-to-find bugs, every bit any role can change them and it tin frequently exist very hard to figure out how a global variable is existence inverse.
    • Some systems may initialize globals to zippo ( see static storage below ), but yous should not count on that.
    • Global variables should be avoided whenever possible. Beginning programmers should not use global variables.
      • Globals are most often required when using callback functions, non covered in this course.
      • The introduction of Exceptions in C++ ( too not covered in this course ) has eliminated much of the former demand for global variables.

    Very Local Variables

    • Variables declared within a { braced block }, such as a loop, if, or switch construct are termed very local variables.
    • The telescopic of very local variables is from the point of declaration to the end of the block in which they are alleged.
      • ( They should normally be declared at the showtime of the block. )
    • Programmers sometimes declare very local variables for temporary variables that are only needed within a particular block.
      • This is unremarkably done to avert proper noun conflict problems with other variables having the same name declared in a more general telescopic. ( See eclipsing below. )
    • Very local variables tin make code hard to read and understand, and should only be used when there is a very good reason to do so.
    • One common apply of very local variables is in the lawmaking fragment:
                  for( int i = 0; i < limit; i++ ) {
    • In this case the loop counter i exists within the body of the loop, and ceases to exist when the loop exits.
    • There will be no disharmonize between this variable i and any other declared at a more general scope. ( See below. )
    • If you choose the variable proclamation mode of declaring all ordinary local variables at the beginning of the function, then any very local variables you declare should be declared at the start of the block in which they are divers.

Variable Eclipsing

  • If the same variable proper name is used in multiple scopes ( e.grand. global, local, very local ), and the scopes overlap,then in the regions of overlap the more specific variable will eclipse, or hide the more general variable(s).
  • When the more specific variable goes out of scope, so the side by side more general variable becomes visible again, unchanged past whatever may accept occurred while information technology was eclipsed.
  • Case. In the code below the comments betoken which Ten will be printed at which locations.
                  void func( int );          double x( 0.0 ); // Global scope          int main( void ) {              printf( "First 10 = %f\north", ten ); // prints the global, 0.0                  int 10 = 42;   // Ordinary local                  printf( "Second ten = %d\northward", x ); // prints the ordinary local, 42                  if( 10 > 40 ) {                      char ten( 'A' ); // Very local, value = 65                          printf( "Third ten = %c\n", x ); // Prints very local, 'A'                          func( 10 ); // Passes the very local char, converted to an int.                      }         printf( "Fifth  x = %d\n", x ); // Ordinary local 42 again                  return 0;     }          void func( int ten ) { // local parameter          	printf( "4th x = %d\north", x ); // Local parameter, 65                  return;     }

      Program Output:

      Showtime x = 0.0
      Second ten = 42
      Third x = A
      Fourth x = 65
      Fifth x = 42

Storage Course

  • Variables can be in 1 of four storage classes, depending on where in reckoner memory they are stored.

    Automatic Variables

    • Automatic variables, ( a.k.a. auto variables ) are stored on a data structure known as "the stack".
    • The stack grows and shrinks as a program executes.
    • In detail, when a new function is entered, space is allocated on the stack to store all of the local variables for that function. ( Actually space is allocated for each variable at the time when it first goes into scope, i.e. when information technology is declared. )
    • More importantly, when the function exits, the stack space allocated to that function is freed up, and becomes available for other uses. ( The stack shrinks. )
    • Local variables, function parameters, and very local variables are ordinarily motorcar variables stored on the stack.
    • Any data stored in car variables is lost when the variables get out of scope, i.e. when a function exits. The next time the variable comes back into scope ( i.e. when the function gets called again ), the variable is allocated new space, and re-initialized if an initialization is given.

    Static Variables

    • Static variables are stored in a split storage surface area known every bit "the heap".
    • Space for static variables is allocated ane time only, before principal( ) begins, and never expires.
    • Global variables are usually static. Other variables may be alleged static.
    • In detail, if function variables are alleged as "static", and so they are only initialized once, and retain their values between office calls. ( The variables can notwithstanding exit of scope, but when they come back into scope they will notwithstanding retain their previous values. )
    • Example: The following code will generate the output shown below the code:
  •               void staticExampleFunction( void );                          int main( void ) {                              for( int i = 0; i < five; i++ )                 	staticExampleFunction( );                                      return 0;                              } // main                          void staticExampleFunction( void ) {                              int normalInt = 0;                 static int staticInt = 0;                                  printf( "The normal int = %d.  The static int = %d.\northward", ++normalInt, ++staticInt );                                  return;             }

    Output:

                  The normal int = 1.  The static int = i.             The normal int = one.  The static int = two.             The normal int = 1.  The static int = 3.             The normal int = 1.  The static int = 4.             The normal int = 1.  The static int = 5.
    • Static variables can be used to count how many times a function is called, or to perform some special beliefs the first time a office is chosen. ( Declare a static variable "firstTime" initialized to true. If firstTime is true, practise the special code so set firstTime to false. )
    • Variation: The static keyword applied to a global variable makes information technology global to this file just, and not visible from other files, ( in a multi-file development project. )

Extern Variables

  • The "extern" keyword applied to a variable indicates that it is declared and allocated space in some other file.
  • A declaration with the give-and-take "extern" is similar a function epitome - It tells the compiler of the beingness of the variable, without actually creating it or allocating whatsoever space for it.
  • All such variables must be declared exactly once, ( i.east. in one file only of a multi-file development project ) without the "extern", and then that space can be allocated for it.
  • Exterm variables are global in the file in which they are declared without "extern", merely may exist either local or global in other files.
  • Extern will be covered more than fully under the topic of multi-file development.

Register Variables

  • The keyword "annals" suggests to the compiler that the given variable be stored in 1 of the CPU registers , ( for faster access ), instead of in regular retention.
  • Register variables act as auto variables, except they exercise not have an "address", and and so cannot be referred to past pointer variables or by the address operator, &.
  • Loop counters are the most common and obvious use of register variables.
  • Modern optimizing compilers take elminated most demand for the keyword annals.

Summary of Variable and Parameter Declaration Qualifiers

The following example shows all possible qualifiers for variables and function parameters, and how those qualifiers bear on the variables in iii cardinal areas:

  1. Storage duration, indicating whether the item continues to be when it goes out of scope ( static storage ), or whether it is re-created and re-initialized every time that it goes into scope ( auto storage. )
  2. Scope, indicating whether the item is bachelor to the remainder of the file ( file scope ), or merely through the residual of the block in which it is defined ( block scope. )
  3. Linkage, indicating whether the detail is as well accessible from other files ( external linkage ) or whether information technology is individual to multiple functions simply inside this file ( internal linkage ), or whether it is accessible only within a cake ( no linkage, i.e. none. )
              int a;         extern int b;         static int c;                  void f( int d, register int e ) {         	machine int chiliad;             int h;             static int i;             extern int j;             register int k;         }
Name Storage Duration Telescopic Linkage

a

static

file

external

b

static

file

??? - come across below

c

static

file

internal

d

auto

cake

none

e

motorcar

cake

none

f

auto

block

none

g

machine

block

none

h

auto

block

none

i

static

cake

none

j

static

block

??? - see below

k

auto

cake

none

??? - The linkage for b and j depends on their original annunciation, but are normally external

Inline Functions ( C99 just )

There is also one additional qualifier that tin can exist applied to functions simply: inline

The ordinary function phone call-and-return mechanism involves a sure amount of overhead, to relieve the state of the original office on the stack, create stack space for a return address and the local ( auto ) variables needed for the new function and its parameters, transfer control to the new function, exercise the work, shop the render value back on the stack, make clean up the stack, then transfer command back to the original calling function.

For certain small fast functions, this overhead can add significantly to the processing time of the function, often greatly surpassing the endeavour needed to perform the work of the office.

Therefore the inline qualifier practical to a function suggests to the compiler to merely copy the instructions for the role into this location in the calling office'southward code, instead of invoking all of the overhead of the call and return process.

An culling to inlined functions is parameterized macros, implemented with #define, which are covered elsewhere.

Related Topics

The following topics are non covered here, but may be plant in many books on C Programming

  • Functions with variable argument lists (. . . )

childersthatted.blogspot.com

Source: https://www.cs.uic.edu/~jbell/CourseNotes/C_Programming/Functions.html

Post a Comment for "In C How Do I End a Function but Then Call It Again"