CSCI 243 The Mechanics of Programming C: Functions Timothy …tvf/CSCI243/Notes/06-c-functions.pdf · TVF / RIT 20195 CS243: Functions Call by Reference • A.k.a. “call by address”,
Post on 17-Aug-2020
5 Views
Preview:
Transcript
CSCI 243The Mechanics of Programming
Timothy Fossum (tvf@cs.rit.edu)
TVF / RIT 20195
C: Functions
TVF / RIT 20195 CS243: Functions
Function Concept
• Convenient bundling of operations• Name is an abstraction for a sequence of operations
• Allows easier decomposition of tasks• Good software engineering practice
• Break a problem down into manageable pieces (modules)
• Implement each module separately
• Keep the interfaces between modules clean and simple
TVF / RIT 20195 CS243: Functions
Function Definition vs. Declaration
• Definition: provides implementation
• scope – optional; determines where function is accessible
• type – data type of return value (void if it doesn’t return a value)
• name – identifier used to invoke the function
• params – optional; formal parameter names, types and ordering (void if there are no parameters)
• body – sequence of operations
[ scope ] type name( [ params ] ) { body }
TVF / RIT 20195 CS243: Functions
Function Definition vs. Declaration
• Declaration: specifies calling sequence
• extern – optional; indicates that function is external to this source file
• type, name – as before
• params – optional; formal parameter types and ordering
• A declaration shows how to use a function, and a definition provides the code to carry out the function.
[ extern ] type name( [ params ] );
TVF / RIT 20195 CS243: Functions
Declaration
• Specifies important calling sequence information:• Name of function
• Type of data being returned
• Number and type of parameters expected by the function
• Not required in C!• Compiler will make assumptions about everything
• Assumes the first reference to an undeclared function is “correct”
• Not a “signature”• Signature is used to resolve overloading
• No overloading in C
• The word prototype is often used to refer to a declaration
TVF / RIT 20195 CS243: Functions
Address Spaces
• Concept: global vs. local entities
• Global: available to entire program, not just this module• A.k.a. external
• Local: available only to limited scopes• Inside a function
• “Local global”: local to a scope which contains other scopes
• E.g., inside a source file but outside a function
TVF / RIT 20195 CS243: Functions
Scope Rules
• Scope modifier: static
• Non-static globals:• Persistent
• Scope is entire program
• Static globals:• Persistent
• Scope limited to this source file
• Non-static locals:• Transient
• Scope limited to this function
• Static locals:• Persistent across function calls
• Scope limited to this function
int v1; // global
static int v2; // static // global
static void f1 (void ) { ...} // also static global
void f2( void ) { int v3; // local static int v4; //static //local ...}
TVF / RIT 20195 CS243: Functions
Scope Example – support.h
//// function prototypes for the supporting functions// called by the 'scope' driver//#ifndef _SUPPORT_H_#define _SUPPORT_H_
////// @function support pass the message into whatever greet()/// function is found for us by the linker/// @param message a (pointer to the) message string
void support( char *message );
#endif
TVF / RIT 20195 CS243: Functions
Scope Example – scope.c (1/2)
//// scope a simple program to demonstrate function scoping rules//// two versions of this program can be compiled://// version 1: gcc Wall std=c99 c scope.c// gcc Wall std=c99 c support1.c// gcc Wall std=c99 o scope1 scope.o support1.o//// version 2: gcc Wall std=c99 c scope.c// gcc Wall std=c99 c support2.c// gcc Wall std=c99 o scope2 scope.o support2.o//#include <stdio.h>
#include "support.h"
TVF / RIT 20195 CS243: Functions
//// this source file has its own greet() function; calls to greet()// from within this file will invoke this version.//// by declaring this as a static function, we prevent it from// being visible outside of this file//
static void greet( char *message ) {printf( "Greetings from scope: %s\n", message );
}
int main( void ) {
// invoke our local greet()greet( "first call to greet()" );
// invoke the support function, which in turn// will invoke greet()support( "call to support()" );
return( 0 );}
Scope Example – scope.c (2/2)
TVF / RIT 20195 CS243: Functions
//// first version of the support() function for the scope example//#include <stdio.h>
#include "support.h"
//// this version doesn't define a greet() function; instead,// we use an extern function declaration to attempt to have// the linker locate it for us//
extern void greet( char * );
//// support(msg) pass the message into whatever greet()// function is found for us by the linker//
void support( char *message ) {greet( message );
}
Scope Example – support1.c
TVF / RIT 20195 CS243: Functions
Scope Example – Using support1.c
% gcc Wall std=c99 c scope.c% gcc Wall std=c99 c support1.c% gcc Wall std=c99 o scope1 scope.o support1.osupport1.o: In function `support':support1.c:(.text+0xd): undefined reference to `greet'collect2: ld returned 1 exit statusmake: *** [scope1] Error 1
TVF / RIT 20195 CS243: Functions
//// second version of the support() function for the scope example//#include <stdio.h>
#include "support.h"
//// this version defines its own greet() function//
static void greet( char *message ) {printf( "Greetings from support: %s\n", message );
}
//// support(msg) pass the message into whatever greet()// function is found for us by the linker//
void support( char *message ) {greet( message );
}
Scope Example – support2.c
TVF / RIT 20195 CS243: Functions
Scope Example – Using support2.c
% gcc Wall std=c99 c scope.c% gcc Wall std=c99 c support2.c% gcc Wall std=c99 o scope2 scope.o support2.o
% ./scope2Greetings from scope: first call to greet()Greetings from support: call to support()
TVF / RIT 20195 CS243: Functions
Function Parameters
• Communication from caller to callee
• Formal parameter• A.k.a. “parameter”
• In function declaration/definition
• Treated like a local variable in terms of scope – never static
• Actual parameter• An expression that matches up with a formal parameter
• The value of this expression is called an “argument”
• How are they passed?
TVF / RIT 20195 CS243: Functions
Parameter Passing Methods in Prog. Languages
• Must associate actual parameters with formals
• The parameter passing “method” determines the caller to callee relationship
• Five classic methods:• Pass by Value
• Pass by Result (Ada’s ‘out’ parameter)
• Pass by Value/result (a.k.a. copy/restore or copy-in-copy-out)
• Pass by Reference
• a.k.a. address, location
• Pass by Name (rare)
• Sometimes we use “Call by” instead of “Pass by”
TVF / RIT 20195 CS243: Functions
Call by Value
• Actual parameter is an r-value• Expression (vs. assignable entity)
• Any expression yielding the correct type is acceptable
• Method:• Evaluate actual parameter
• Associates the formal parameter to the value of the actual parameter
• Changes to formal are not propagated back to caller
• Default mode in many languages• Pascal, Modula-2, C++, etc.
• Ada: “in” parameter
• Available as an option in some languages (Algol 60)
• Unavailable in some languages (Fortran I, IV)
• In C: all parameters except arrays
TVF / RIT 20195 CS243: Functions
Call by Reference
• A.k.a. “call by address”, “call by location”
• L-value of actual parameter is passed in• Must be “assignable” → must be a variable
• Formal parameter is associated with the location of the actual param.
• Formal parameter serves as an alias for the actual• R-value access to the formal causes dereferencing
• Default mode in many languages• Only mode originally available in Fortran
• Even constants were passed by reference (!)
• C++ has an optional reference specification
• Java passes object references, but it’s not quite call by reference
• In C: only array parameters
TVF / RIT 20195 CS243: Functions
Parameter Example – parameters.c (1/5)
//// a simple program to illustrate the difference between// passing scalar parameters and passing array parameters//// to compile: gcc Wall std=c99 o parameters parameters.c//
// this is required to get srand48() and lrand48() prototypes#define _DEFAULT_SOURCE
#include <stdio.h>#include <stdlib.h>#include <time.h>
// number of elements in the array we'll pass#define NUM_ELEMENTS 12
TVF / RIT 20195 CS243: Functions
Parameter Example – parameters.c (2/5)
//// this function modifies both of its parameters;// however, the first parameter is a scalar, and// is passed in by value, so the modification only// affects the local copy//
void tweak( int num, int data[] ) {
while( num >= 0 ) {if( (num % 2) ) {
data[num] += 5;} else {
data[num] = 5;}
}}
TVF / RIT 20195 CS243: Functions
Parameter Example – parameters.c (3/5)
int main( void ) {int values[NUM_ELEMENTS];int i, n;
// to make this program a bit more interesting,// use this call to srand48() and every run of// the program will generate a different sequence// of random values// srand48( (long) time(NULL) );
srand48( (long) 41 );
// initialize the contents of our arrayfor( i = 0; i < NUM_ELEMENTS; ++i ) {
values[i] = lrand48() % 1000;}
n = NUM_ELEMENTS;
TVF / RIT 20195 CS243: Functions
Parameter Example – parameters.c (4/5)
n = NUM_ELEMENTS;
// report the number of elements and their values// before we invoke the tweak() routine
printf( "%d elements before tweaking:\n", n );for( i = 0; i < NUM_ELEMENTS; ++i ) {
printf( " values[%2d] = %5d", i, values[i] );if( ((i+1) % 3) == 0 ) {
putchar( '\n' );}
}putchar( '\n' );
TVF / RIT 20195 CS243: Functions
Parameter Example – parameters.c (5/5)
// time to tweak things a bittweak( n, values );
// report the number of elements and the resulting// values after calling tweak()
printf( "%d elements afer tweaking:\n", n );for( i = 0; i < NUM_ELEMENTS; ++i ) {
printf( " values[%2d] = %5d", i, values[i] );if( ((i+1) % 3) == 0 ) {
putchar( '\n' );}
}putchar( '\n' );
return( 0 );}
TVF / RIT 20195 CS243: Functions
Parameter Example – Using parameters.c
% gcc Wall std=c99 c parameters.c% gcc Wall std=c99 o parameters parameters.o
% ./parameters12 elements before tweaking: values[ 0] = 192 values[ 1] = 969 values[ 2] = 705 values[ 3] = 341 values[ 4] = 507 values[ 5] = 411 values[ 6] = 160 values[ 7] = 51 values[ 8] = 821 values[ 9] = 708 values[10] = 326 values[11] = 584
12 elements afer tweaking: values[ 0] = 187 values[ 1] = 974 values[ 2] = 700 values[ 3] = 346 values[ 4] = 502 values[ 5] = 416 values[ 6] = 155 values[ 7] = 56 values[ 8] = 816 values[ 9] = 713 values[10] = 321 values[11] = 589
TVF / RIT 20195 CS243: Functions
Recursion
• Direct• Function a() calls itself
• Indirect/mutual• Function a() calls b()
• Function b() then calls a()
• Each incarnation gets its own:• Parameters
• Local variables
• Critical component: runtime stack
TVF / RIT 20195 CS243: Functions
Recursion Example – factorial.c (1/4)
//// classic problem: compute the factorial of an integer//// to compile: gcc Wall std=c99 o factorial factorial.c//
#include <stdio.h>#include <stdlib.h>#include <time.h>
TVF / RIT 20195 CS243: Functions
Recursion Example – factorial.c (2/4)
//// fact(depth,num) return the factorial of 'num'//// the 'depth' parameter is used to illustrate the levels// of recursion used to calculate the factorial//
unsigned int fact( int depth, unsigned int num ) {int i;unsigned int result = num;
// give a visual indication of recursion depthfor( i = 0; i < depth; ++i ) {
putchar( ':' );}
TVF / RIT 20195 CS243: Functions
Recursion Example – factorial.c (3/4)
// report that we're computing the factorial of 'num'printf( "%u! = %u", num, num );if( num > 1 ) {
// by recursively computing the factorial of 'num'1printf( " * %u!\n", num 1 );result *= fact( depth + 1, num 1 );
} else {putchar( '\n' );
}
return( result );
}
TVF / RIT 20195 CS243: Functions
Recursion Example – factorial.c (4/4)
//// compute(num) compute the factorial of 'num', and// issue a report to the user about it//void compute( unsigned int num ) {
printf( "\nCalculating %u!\n", num );printf( "%u! = %u\n", num, fact(1,num) );
}
int main( void ) {
// compute a few factorials
compute( 5 );compute( 1 );compute( 3 );
return( 0 );}
TVF / RIT 20195 CS243: Functions
Recursion Example – Using factorial.c
% gcc Wall std=c99 c factorial.c% gcc Wall std=c99 o factorial factorial.o
% ./factorial
Calculating 5!:5! = 5 * 4!::4! = 4 * 3!:::3! = 3 * 2!::::2! = 2 * 1!:::::1! = 15! = 120
Calculating 1!:1! = 11! = 1
Calculating 3!:3! = 3 * 2!::2! = 2 * 1!:::1! = 13! = 6
top related