145
1 Department of Computer Science and Engineering, HKUST HKUST Summer Programming Course 2008 Function ~ Modular Programming

HKUST Summer Programming Course 2008

  • Upload
    dionne

  • View
    19

  • Download
    0

Embed Size (px)

DESCRIPTION

HKUST Summer Programming Course 2008. Function ~ Modular Programming. Overview. Introduction to Functions Standard Libraries (cmath, cctype, cstring, ctime, cstdlib) User-defined function Pass-by-value and Pass-by-reference Local and Global scope Identifiers Name Resolution - PowerPoint PPT Presentation

Citation preview

Page 1: HKUST Summer Programming Course 2008

1Department of Computer Science and Engineering, HKUST

HKUST SummerProgramming Course 2008

Function

~ Modular Programming

Page 2: HKUST Summer Programming Course 2008

2

Overview Introduction to Functions Standard Libraries (cmath, cctype, cstring, ctime, cstdlib) User-defined function Pass-by-value and Pass-by-reference Local and Global scope Identifiers Name Resolution Function Definition and Declaration Function Overloading and Default Parameter Separate Compilation (Function Level) Header Files g++ and Makefile Function Execution in Runtime Static Variables in Function Definition Inline Function and its Compilation Model

Page 3: HKUST Summer Programming Course 2008

3Department of Computer Science and Engineering, HKUST

Function

Introduction to Functions

Page 4: HKUST Summer Programming Course 2008

4

Introduction to Functions So far, the code we learnt were completely specified within

main() This was possible because the code is simple and easy.

However, a large software application requires hundreds of thousands, or even millions lines of code. Impractical to write a single piece of code for such a large

application. Therefore, modular design principal is introduced, to put a

small, but meaningful, piece of code together. Other parts of program can use this piece of code once (or several

times code reuse). A principal part of all such schemes is the use of functions.

Page 5: HKUST Summer Programming Course 2008

5Department of Computer Science and Engineering, HKUST

Function

Standard Libraries (cmath, cctype, cstring, ctime, cstdlib)

Page 6: HKUST Summer Programming Course 2008

6

Standard Libraries (cmath, cctype, cstring, ctime, cstdlib)

Before learning how to write a function, let’s see some standard libraries defined by C++ cmath (Math functions) cctype (Character functions) cstring (Character string functions) ctime (time-related functions) cstdlib (commonly-used functions)

To use cmath, you have to include the library by #include <cmath>using namespace std;

You can include other libraries similarly. Good reference: http://www.cplusplus.com/ref/.

Page 7: HKUST Summer Programming Course 2008

7

Standard Libraries (cmath) double ceil(double x)

Smallest integer greater than or equal to x. ceil(3.2) = 4, ceil(3.7) = 4, ceil(-3.2) = -3, ceil(-3.7) = -3

double floor(double x) Largest integer less than or equal to x.

floor(3.2) = 3, floor(3.7) = 3, floor(-3.2) = -4, floor(-3.7) = -4 Other rounding methods

Cast as integer Truncate the floating-point part

(int)(3.2) = 3, (int)(3.7) = 3, (int)(-3.2) = -3, (int)(-3.7) = -3 Round to nearest integer (no default function).

round(3.2) = 3, round(3.7) = 4, round(-3.2) = -3, round(-3.7) = -4

Page 8: HKUST Summer Programming Course 2008

8

Standard Libraries (cmath)

int abs(int x) Absolute value of x (integer version).

double fabs(double x) Absolute value of x (floating-point version).

Common errorsdouble x = -3.2;

double absX = abs(x); C++ will convert x into int and then apply abs.

result = 3, but not 3.2 Use fabs instead.

Page 9: HKUST Summer Programming Course 2008

9

Standard Libraries (cmath)

double exp(double x) ex

double pow(double x, double y) xy

double sqrt(double x) Square root of x

double log(double x) Natural log of x

double log10(double x) Log base 10 of x

Page 10: HKUST Summer Programming Course 2008

10

Standard Libraries (cmath) double sin(double x)

Sine of angle x (in radian). double asin(double x)

Angle (in radian) whose sine is x. double cos(double x)

Cosine of angle x (in radian). double acos(double x)

Angle (in radian) whose cosine is x. double tan(double x)

Tangent of angle x (in radian). double atan(double x)

Angle (in radian) whose tangent is x.

Page 11: HKUST Summer Programming Course 2008

11

Standard Libraries (cctype) int isalpha(char c)

true if c is a letter. Non-zero value means true

int isdigit(char c) true if c is a digit.

int isalnum(char c) true if c is a letter or digit.

int isblank(char c) true if c is a blank or tab.

int isspace(char c) true if c is whitespace character.

space, tab, vertical tab, formfeed, carriage return, or newline.

Page 12: HKUST Summer Programming Course 2008

12

Standard Libraries (cctype)

int islower(char c) true if c is a lowercase letter.

int isupper(char c) true if c is an uppercase letter.

int tolower(char c) returns lowercase version of c if there is one, otherwise it returns the

character unchanged. We can cast the return value back to char.

int toupper(char c) returns uppercase version of c if there is one, otherwise it returns

the character unchanged.

Page 13: HKUST Summer Programming Course 2008

13

Standard Libraries (cstring)

size_t strlen(const char* str) Return str’s length.

typedef unsigned int size_t; char* strcat(char* dest, const char* src)

Appends src string to dest string. char* strcpy(char* dest, const char* src)

Copies src to dest. int strcmp(const char* str1, const char* str2)

Compares str1 to str2 character by character. Returns 0 if str1 is equal to str2. Returns >0 if str1 is greater than str2. Returns <0 if str1 is less than str2.

Page 14: HKUST Summer Programming Course 2008

14

Standard Libraries (cstring)

char* strtok(char* str, const char* delimiters) Sequentially truncate string if delimiter is found. Useful in parsing input, for example:

char input[100];

strcpy( input, "Name=Desmond;Mark1=100;Mark2=99");

char* pch = strtok(input, “=");

int fieldID = 0;

while ( pch != NULL ) {

cout << pch << endl;

if ( fieldID % 2 == 0 )

pch = strtok(NULL, “;"); // continue to use, use NULL

else pch = strtok(NULL, “=");

++fieldID;

}

More on this when we are talking about static variable.

Output:NameDesmondMark1100Mark299

Page 15: HKUST Summer Programming Course 2008

15

Standard Libraries (ctime) time_t time ( time_t * timer )

Get the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC from the system clock. typedef long clock_t; This will overflow in the year 2038, if 32-bit long is used !!

char* ctime( const time_t* timer ) Converts timer to a string containing time and date adjusted to local

time zone in the format Www Mmm dd hh:mm:ss yyyy. clock_t clock ()

Returns the number of clock ticks elapsed. Useful in measuring time for an expensive job.

clock_t start = clock( );// expensive jobclock_t end = clock( );cout << “Elapsed seconds = “ << (end-start)*CLK_TCK;

Page 16: HKUST Summer Programming Course 2008

16

Standard Libraries (cstdlib)

double atof( const char* string ) Convert string to double.

int atoi( const char* string ) Convert string to int.

void qsort( void* base, size_t num, size_t width, int (*fncompare)(const void *, const void *) ) Sort the array with quick-sort algorithm. More about this when we are talking function pointer.

Page 17: HKUST Summer Programming Course 2008

17

Standard Libraries (cstdlib) void exit( int status );

Terminate calling process, return status to OS. char* getenv( const char* varname )

Get system environment variable.char* buffer = getenv ("PATH"); if (buffer != NULL)

cout << "Current path is” << buffer << endl; Linux separates PATH with semicolon, you can use strtok to

separate the path from the long string. int system( const char* command )

Execute command.int status = system(“ls"); if (status == -1)

cout << "Error executing ls\n”;

Page 18: HKUST Summer Programming Course 2008

18

Standard Libraries (cstdlib) int rand()

Generate a pseudo-random number in the range from 0 to RAND_MAX. RAND_MAX is also defined in <cstdlib>

void srand( unsigned int seed ) Initialize the random seed once at the beginning of main( ). Eg.: srand( time(NULL) );

Random generator depends on two parameters. Seed (initialized with srand) Number of rand() called

Detail can be found in lab manual (lab03).

Page 19: HKUST Summer Programming Course 2008

19

Standard Libraries

Guarantee: If it is necessary to use any standard functions in exam, a

brief description of that function will be given. Say, function prototype and function description.

No memorization is needed!!

Page 20: HKUST Summer Programming Course 2008

20Department of Computer Science and Engineering, HKUST

Function

User-defined Function

Page 21: HKUST Summer Programming Course 2008

21

User-defined function

Function Definition Syntax

<return-type> <function name>(<parameter list>){

// function body

}

Function call Syntax

<function name>( <variable list> )

Page 22: HKUST Summer Programming Course 2008

22

Function Name

<function name> can be any valid C++ identifier. It is a good practice to use a meaningful function name.

To describe the tasks that the function performs.

Page 23: HKUST Summer Programming Course 2008

23

Parameter List The parameter list is a comma-separated list of variables (with

their types) that receive values of the arguments when the function is called. If no parameters is needed, the parameter list is empty.

However, even if there are no parameters, parentheses are required. Syntax

<return-type> <function name>(<type1> <name1>, <type2> <name2>, …, <typeN><nameN>){// function body

}int func(int i, int k, int j){ ... } // correctint func(int i, k, int j){ ... } // incorrectint func( ){ ... } // correct

It is a good practice to select meaningful identifiers for the parameters.

Page 24: HKUST Summer Programming Course 2008

24

Parameter List

In old C, it is not allowed to use <return-type> <function name>( )

to define a function. Instead, it will use

<return-type> <function name>( void ), where void is a reserved word that specify there is no argument in this function.

In ANSI C/C++, these two forms are equivalent. C++ is backward compatible with C!!

Page 25: HKUST Summer Programming Course 2008

25

Function Calling - Variable List Syntax

<function name> (<variable list>); <variable list> is a comma-separated list of variables

The type of the variable must be the same as the type specified in <parameter list>. Or auto-convertible to the type specified in <parameter

list>. For example,

int a;double b, c;func(a, b, c); // function call, b is converted to int for the functionint func(int i, int k, double j){ ... }

Page 26: HKUST Summer Programming Course 2008

26

Function header VS function bodyint func(int a, int b, int c){

// function body

} The first line is called function header:

<return-type> <function name>(<parameter list>) The code inside the curly-brace is called function body. The whole piece of code is called function definition.

Terminology

Page 27: HKUST Summer Programming Course 2008

27

Terminology

Formal Parameters VS Actual Parametersint func(int i, int k, int j){ ... }// function definition

func(a, b, c); // function call

The parameters in the function header is called formal parameters, or parameters ONLY. Here, i, k, j are formal parameters.

The variables used in the function call is called actual parameters, or arguments. Here, a, b, c are actual parameters.

Page 28: HKUST Summer Programming Course 2008

28

Return Value <return-type>: specifies the type of data that the function

returns. A function may return any type of data EXCEPT an array.

A function can either return a single result or return nothing. To return nothing, we can put void in the <return-

type>. The return value may either

Signals whether an operation is successful or not. Result of computation. ……

If multiple parameters need to be returned, use passing by reference (will be covered in a minute).

Page 29: HKUST Summer Programming Course 2008

29

Return Value

The function caller may ignore the returned value But this is not a good practice. Some compilers even flag this as a warning.

Non-void return-typed function should have one or more return statements: return <expression>; The value passed back by return should have the same type as

the <return-type> of the function. Or a type that can be converted to <return-type> automatically.

Return statement also indicates the end of the function. Therefore, void function can also have a statement likes:

return;

Page 30: HKUST Summer Programming Course 2008

30

Function Body

function body defines how the function do. Note the function body is enclosed by braces { } It can include any number of statements. Even if there is only one statement, you cannot omit the

braces { } This is different from the if-statement and iterative

statements.

Page 31: HKUST Summer Programming Course 2008

31

Example of user-defined function (1)

int add(int val1, int val2) {return val1 + val2;

}

int main() {cout << "Enter two integers: ";

int v1, v2;

cin >> v1 >> v2;

cout << "The sum is " << add(v1,v2) << endl;

return 0;

}

Page 32: HKUST Summer Programming Course 2008

32

Example of user-defined function (2)

We can implement the tolower (defined in cctype) ourselves.// Convert an upper-case letter to lower case

// Keep it unchanged if it is not an upper-case letter

int tolower(char c) {

if ( c >= ‘A’ && c <= ‘Z’ )

return ( c – ‘A’ + ‘a’ );

else

return c;

} No need to memorize the ASCII table!!

Page 33: HKUST Summer Programming Course 2008

33

Example of user-defined function (3)

Now, try to implement a round function ourselves.

int round( double x ) {

if ( x >= 0 )

return (x + 0.5);

else

return (x - 0.5);

}

C++ will convert the returned value to the desired type. (x+0.5) is a double, but it will cast back to int

automatically.

Page 34: HKUST Summer Programming Course 2008

34

Example of user-defined function (3)

// here is definition of the function: round

int main( ) {double x1 = 3.2, x2 = 3.7, x3 = -3.2, x4 = -3.7;cout << ceil(x1) << “ “ << ceil(x2) << “ “ <<

ceil(x3) << “ “ << ceil(x4) << endl;cout << floor(x1) << “ “ << floor(x2) << “ “ <<

floor(x3) << “ “ << floor(x4) << endl;cout << (int)(x1) << “ “ << (int)(x2) << “ “ <<

(int)(x3) << “ “ << (int)(x4) << endl;cout << round(x1) << “ “ << round(x2) << “ “<<

round(x3) << “ “ << round(x4) << endl;return 0;

}

Page 35: HKUST Summer Programming Course 2008

35

Example of user-defined function (4)

void formattedOutput(char* name, int mark1, int mark2){cout << “Name: “ << name << endl;cout << “Midterm mark: “ << mark1 << endl;cout << “Final Exam mark: “ << mark2 << endl;

}

int main( ) {char* name = “Desmond”;int midtermMark = 100; int finalExamMark = 90;formattedOutput(name, midtermMark, finalExamMark);return 0;

}

Page 36: HKUST Summer Programming Course 2008

36

Example of user-defined function (5)

These two function definitions are equivalentvoid printWelcome(void) {

cout << “Hello World” << endl;

}

void printWelcome() {

cout << “Hello World” << endl;

}

Page 37: HKUST Summer Programming Course 2008

37

Documentation for functions It is a good practice to document the functions (ie. add

sufficient comment to the function). Describe the task that the function performs. Describe the meaning of each parameter. Describe the meaning of the returned value.

For example, /* Convert the character c to lowercase letter if

c is a uppercase letterOtherwise, keep the character c unchanged */int tolower(char c) { … }

/* Round x into nearest integerInput: x, any real numberOutput: nearest integer of x */int round( double x ) { … }

Page 38: HKUST Summer Programming Course 2008

38Department of Computer Science and Engineering, HKUST

Function

Pass-by-value and Pass-by-reference

Page 39: HKUST Summer Programming Course 2008

39

Pass-by-value and Pass-by-reference

In C++, there are two ways that the arguments can be passed to a function: Pass-by-value Pass-by-reference

Page 40: HKUST Summer Programming Course 2008

40

Pass-by-value

Pass-by-value copies the value of an actual parameter into the formal parameters of the function. Changes made to the formal parameter have no effect on the

actual parameter.

Page 41: HKUST Summer Programming Course 2008

41

Examples

int sum(int a, int b) {a = a + b;return a;

}int main() {

int x = 3, y = 5;int z= sum(x,y);return 0;

} What’s the value of x, y, z after the function call sum?

Ans: 3, 5, 8

Page 42: HKUST Summer Programming Course 2008

42

Examples

Reasons: The value of the original variable is copied to the parameter.

changes to the value of the parameter do not affect the original variable.

Even though the value of parameter a is changed, the corresponding value in variable x does not change.

In fact, all information in local variables declared within the function will be lost when the function terminates. The only information saved from a pass by value function is the

return value.

Page 43: HKUST Summer Programming Course 2008

43

Pass-by-reference

Pass-by-reference does not copy the value of the actual parameters. Instead, the formal parameters refer the actual parameters

by some mechanism. More about this later, when we are talking about reference

variable. Any modification of the formal parameters directly changes

the value of the actual parameters. To pass the parameters by reference, we have to add a

symbol & after the type of the formal parameters.

Page 44: HKUST Summer Programming Course 2008

44

Examples

void swap(int& a, int& b) {int temp = a;a = b;b = temp;

}int main() {

int x = 10, y = 20;swap(x, y);cout << “(x, y) = “ << x << ", " << y ;return 0;

} What’s the output?

(x,y) = 20, 10

Page 45: HKUST Summer Programming Course 2008

45

Examples

Explanation: Note that two formal parameters are pass-by-reference.

The formal parameter a refers to the actual parameter x. The formal parameter b refers to the actual parameter y.

The value of a and b are changed inside the function. This is equivalent to modify the actual parameters x and y

directly.

Page 46: HKUST Summer Programming Course 2008

46

Examples

void swap(int a, int b) {int temp = a;a = b;b = temp;

}int main() {

int x = 10, y = 20;swap(x, y);cout << “(x, y) = “ << x << ", " << y ;return 0;

} What’s the output?

(x, y) = 10, 20 (unchanged!!)

Page 47: HKUST Summer Programming Course 2008

47

Final Note on Pass-by-value and Pass-by-reference

A function can contain multiple parameters. Some may be pass-by-value, while other may be pass-by-reference. No restriction on the order of pass-by-value and pass-by-reference.

If a function has multiple return values, we may use pass-by-reference. void largestTwoElements(const int* array, int size,

int& largest, int& secondLargest) Sometimes, when the object is large, we may use pass-by-

reference to avoid copying even if we don’t want to change the actual parameters. Use constant reference (add const before the type). More on this when we are talking about class.

Page 48: HKUST Summer Programming Course 2008

48Department of Computer Science and Engineering, HKUST

Function

Local and Global scope

Page 49: HKUST Summer Programming Course 2008

49

Scope Scope is a region of code.

We can define a scope by enclosing a piece of code within curly-braces.

It is possible to declare the same identifier name in different scopes. Because an identifier is both identified by its name and the scope

where it is defined. Identifiers defined in different scopes are treated as different

identifiers, even if their name are the same. But an identifier should have unique name inside a scope.

The outermost scope is called global scope. All other scopes (may be called local scope) are inner scopes of

global scope. More about this when we are talking about namespace.

Page 50: HKUST Summer Programming Course 2008

50

Global and Local Declaration Declaration inside global scope is called global declaration.

It is valid inside all other scopes (or in the whole program). Declaration inside local scope is called local declaration.

It is valid inside that local scope or other inner scopes . Of course, it is only valid after its declaration inside that

scope.

Page 51: HKUST Summer Programming Course 2008

51

Global Variables Global variables

Declared outside all the function bodies (including main function).

Known throughout the program and may be used by any pieces of code.

They are normally grouped with the other global variables and placed at the beginning of the program file.

Global variable can be accessed in any parts of program Difficult to manage (trace, testing and debug the code). It is a bad practice to use global variables.

Try to avoid them if possible. To communicate between functions, passing local variables by

reference.

Page 52: HKUST Summer Programming Course 2008

52

Local Variables

Local variables Declared inside a scope, except global scope. Known by statements that are inside the block in which the

variables are declared. Not known outside their own scope and it is destroyed

automatically upon exit. Note that formal parameters of a function are also local

variables of that function.

Page 53: HKUST Summer Programming Course 2008

53

Page 54: HKUST Summer Programming Course 2008

54

y is accessible

f is accessible

z is accessible

a is accessible

s, t are accessible

r is accessible

i is accessible

Page 55: HKUST Summer Programming Course 2008

55

Variable Definition in For-loop

for(int i=0; i<10; i++)

cout << “Hello ” << i << endl;

cout << “Printed Hello for “ << i << “times” << endl;

This is compilable in VC6, but not in g++, which follows the standard. According to C++ standard, a variable defined inside the for-init of the for loop should be treated like:{ // a scope is created to enclose the whole for-loop

for (int i=0; i<10; i++){

cout << “Hello” << i << endl;

}

}

// therefore , the variable i cannot be accessed

cout << “Printed Hello for “ << i << “times” << endl;

Page 56: HKUST Summer Programming Course 2008

56Department of Computer Science and Engineering, HKUST

Function

Identifiers Name Resolution

Page 57: HKUST Summer Programming Course 2008

57

Identifiers Name Resolution When a compiler read an identifier, how it relates this identifier

to a declaration of identifier is called Name Resolution. Function name Variable name

When is an identifier encountered in a scope, Compiler first tries to find a declaration in that scope.

If a declaration is found in that scope, finish. Otherwise, search the declaration in the smallest “outer scope”. Continue until the compiler reach the global scope. If a declaration still cannot be found, flag a compile error reports that

the identifier cannot be resolved.

Page 58: HKUST Summer Programming Course 2008

58

Examplesint a = 10, b = 3; // global definition

int func( int b, int c ) {int sum = a; // a: no definition in func scope, use

// global definitionreturn (sum + b + c); // b, c, sum: definition in func scope

// found}

int main( ) {int a = 100, b = 200;while ( a > 0 ) { // a: definition in main( ) scope

int b = 10;a -= b; // a: main() scope; b: while

loop scope}return b; // b: definition in main( ) scope

}

Page 59: HKUST Summer Programming Course 2008

59

Global Scope’s identifier

int a = 10;

int main( ) {

int a = 100;

cout << “a = “ << a << endl;

} It will print the local declaration of a.

How to print the global scope’s a?

Page 60: HKUST Summer Programming Course 2008

60

Global Scope’s identifier

int a = 10;

int main( ) {

int a = 100;

cout << “Local declaration of a = “ << a << endl;

cout << “Global declaration of a = “ << ::a << endl;

}

Use the scope operator ::, to explicitly tell the compiler to use the global declaration of a.

Page 61: HKUST Summer Programming Course 2008

61

Example

int a = 1;int main( ) {

int a = 100;while (1) {

int a = 10;cout << a << endl; // a: while loop scopecout << ::a << endl; // a: global scope

}return 0;

} However, you can’t access the declaration of “a” defined in the

main( ) scope.

Page 62: HKUST Summer Programming Course 2008

62

Example

In practice, rename the identifier to avoid name collision. Longer identifier name is less likely to occur name collision. Easier to trace the program. Try all possible ways to avoid uses of global variable.

Page 63: HKUST Summer Programming Course 2008

63Department of Computer Science and Engineering, HKUST

Function

Function Definition and Declaration

Page 64: HKUST Summer Programming Course 2008

64

Call a function without declaration

In C++, all functions must be declared before use. For example, the following code resulted a compile error

int main() { int i = 1, j = 2; return add(i, j); }

int add(int val1, int val2) { return (val1 + val2); } ERROR: The function add is used in main function without

declaration.

But this will be correct.int add(int val1, int val2) { return (val1 + val2); }

int main() { int i = 1, j = 2; return add(i, j); }

Page 65: HKUST Summer Programming Course 2008

65

Function definition and declaration Note that declaration is not the same as definition in C++.

Declaration means introducing an identifier (with its type). Variable / Function declaration.

Definition means giving the identifier a value or its functionality. Variable / Function definition.

Variable definition/declaration will not be covered in this course because it involves some other concepts. If you are interested, we can discuss after class. We will focus on function declaration/definition here.

A function must be declared before use, but it is not necessary to be defined before use. So that the compiler can determine whether there are any type

mismatch errors in the variables passed in function call.

Page 66: HKUST Summer Programming Course 2008

66

Function definition and declaration So far, all functions are declared and defined at the same time.

int add(int val1, int val2) {return val1 + val2;

} The above three lines together are called function definition. A function definition will also introduce the identifier, and hence it is

also a kind of declaration. We can also declare a function without defining it immediately.

int add(int val1, int val2); // function header only The above line is called function declaration. A semicolon must appear at the end.

Page 67: HKUST Summer Programming Course 2008

67

Function Declaration

To declare a function, it is not necessary to give the identifier name for the formal parameters. The following two are equivalent:

int add(int val1, int val2);

int add(int, int); But it is recommended to give the identifier name, since this helps

others to guess the meaning of the parameters. The type of the formal parameters must be given in function

declaration.

Page 68: HKUST Summer Programming Course 2008

68

Function Declaration

In a program, A function can be declared many times. But a function can only be defined once.

If you define a function several times, the compiler cannot determine which function definitions should be used.

Page 69: HKUST Summer Programming Course 2008

69

Function Declaration

Currently, it seems that it is not necessary to declare a function.

But it will be necessary when we are talking about: Separate compilation. Recursive programming.

You can view function declaration as a guarantee that the function will be defined, but not defined at this moment. Although you can omit the function definition if there is no

one call that function.

Page 70: HKUST Summer Programming Course 2008

70

Common pitfalls of function declaration and function definitionint main() {

int i = 1, j = 2; return add(i, j); // compile error: no declaration before use

}

int add(int val1, int val2) { return (val1 + val2);

}

/////////////////////////////////////////////////////////////

int add(int val1, int val2);int main() {

int i = 1, j = 2; return add(i, j); // linking error: add has not been defined

}

Page 71: HKUST Summer Programming Course 2008

71

Common pitfalls of function declaration and function definition

int add(int val1, int val2);

int main() { int i = 1, j = 2; return add(i, j); // linking error: no

// add(int,int) is defined}

double add(double val1, double val2){

return (val1 + val2); }

Page 72: HKUST Summer Programming Course 2008

72Department of Computer Science and Engineering, HKUST

Function

Function Overloading and Default Parameter

Page 73: HKUST Summer Programming Course 2008

73

Function Overloading

It is sometimes difficult to name several similar (but different) functions with several different names int absInt(int i); double absDouble(double d); etc.

C++ allows using one name for several functions through function overloading.

Page 74: HKUST Summer Programming Course 2008

74

Function Signature We use signature to identify a person. C++ also identify a function with its function signature,

which includes: Function Name. Types of Parameters. Number of Parameter.

No two functions in C++ can have the same signature. But a function with the same name, but with different type of

parameters can be co-exist. This is known as function overloading.

Note that return type and identifier of input parameters are not parts of function signature.

Page 75: HKUST Summer Programming Course 2008

75

Function Overloading

For example, the following functions can be co-exist: int abs(int i); double abs(double d); long abs(long l);

Since all of them takes different types of input. Another example is:

int func(int a, int b); int func(int a, double b); int func(int a, int b, int c);

Page 76: HKUST Summer Programming Course 2008

76

Function Overloading

However, the following functions cannot co-exist with the function int func(int a, int b); int func(int c, int d);

Identifiers of input parameters are not part of signature. double func(int a, int b);

Return type is not part of signature.

Page 77: HKUST Summer Programming Course 2008

77

Function Overloading

// abs is overloaded in three ways

int abs(int i) { return i<0 ? -i : i; }

double abs(double d) { return d<0 ? -d : d; }

long abs(long l) { return l<0 ? -l : l; }

int main() {

cout << abs(-10) << “ “ << abs(-11.0) << “ “ << abs(-9L) << endl;

return 0;

}

C++ will determine which function should be called from the type of the actual parameters. The type of (first) parameter in abs(-11.0) is of double

type, C++ will call the version with single input parameter of double type automatically.

Page 78: HKUST Summer Programming Course 2008

78

Function Resolution

When an actual parameter do not match the formal parameter, C++ will try to convert the actual parameter to the type of formal parameter.

This process is complicated in function overloading, for example, consider the following two overloaded functions:int abs(int i) { return i<0 ? -i : i; }

double abs(double d) { return d<0 ? -d : d; } Which version of function should be matched to the call of

abs(3.5f)? OR should 3.5f (float) be converted to int or double?

Page 79: HKUST Summer Programming Course 2008

79

Function Resolution C++ formally defined a set of rules to handle this difficulties

arose in function overloading. The (long) list of rules are difficult to memorize and not very

useful in practical programming. We will not have too many functions overloaded in practice.

In general, the idea of the rules are: Exact match will be first used. “Non-narrowing” conversion will be secondly used. “Narrowing” conversion will be lastly used.

Therefore, “abs(-3.5f)” will call the double-version, which corresponds to a “non-narrowing” conversion, instead of int-version, which corresponds to a “narrowing” conversion.

Page 80: HKUST Summer Programming Course 2008

80

Function Resolution

Consider the following two overloaded functionsint func(int a, double b);

int func(double a, int b); The function call func(3.2, 4.6) can either

Match to the first version by “narrowing converting” the first parameter to int.

Match to the second version by “narrowing converting” the second parameter to int.

No conversion is at higher priority than the other.

Ambiguity resulted (compile error). Use func( (int)3.2, 4.6 ) to call the first version.

Page 81: HKUST Summer Programming Course 2008

81

Default Parameter

Sometimes, two overloaded functions are very similar, for example:void sort( int* array, int size );

void sort( int* array, int size, bool isAscending ); The first version sorts the array in ascending order, while the

second version sorts the array in an order specified by the flag isAscending.

Notice that the second function is a general case of the first function.

Page 82: HKUST Summer Programming Course 2008

82

Default Parameter

To increase code reusability, C++ allows us to use default parameter

void sort( int* array, int size, bool isAscending = true ) {

if ( isAscending )

; // sort in ascending order

else

; // sort in descending order

}

Defining this function essentially defined two overloaded functions (underlying, not really define two functions). void sort(int*, int, bool); void sort(int*, int);

Page 83: HKUST Summer Programming Course 2008

83

Default Parameter Note that default parameters must be specified at the end of the

parameter list.void sort( int* array, int size, bool isAscending = true ); But not

void sort( bool isAscending = true, int* array, int size ); A function can have several default parameters, for example,

int calcSomeResult(int a, float b, int c = 1, float d = 2); All default parameters should be at the end of the parameter list.

The default value (eg. true, 1, 2) can either be specified in function definition or function declaration, but not both. Usually, we put it in the function declaration. Therefore, the user of your function can know what is the default

value, without reading the implementation.

Page 84: HKUST Summer Programming Course 2008

84

Default Parameter

Since the above function essentially defining two functions: void sort(int*, int, bool); void sort(int*, int);

If you define another function void sort(int*, int), and call the function sort( array, 10 ), this will result in ambiguity in the call of functions.

Page 85: HKUST Summer Programming Course 2008

85

Example – Default Parameter (new slide)void sort( int* array, int size, bool isAscending = true ) {

if ( isAscending )cout << “ascending” << endl;

else cout << “descending” << endl;}

int main(){int array[] = {1,10,9,3,10};sort( array, 5, true );sort( array, 5, false );sort( array, 5 );return 0;

}

Output:

ascendingdescendingascending

Page 86: HKUST Summer Programming Course 2008

86

Other forms of overloading

You can also define a function with any number of parameters (with the help of ellipses list). For example,

void printf( const char*, ...); Here, the three dots ... is a syntax in C++, which is called ellipses

list. It represents any number of parameters.

Therefore, we can call the printf with:printf( “Hello World” );

printf( “Give me %d dollars”, dollar );

printf( “Division tutorial: %f/%f = %f”, x, y, x/y);

Page 87: HKUST Summer Programming Course 2008

87

Other forms of overloading Recall that one of the advantages of C++ is strongly typed.

The compiler will check the datatype for us. This reduces a large number of runtime errors.

Using ellipses list prevents the compiler from checking the type.int x = 10;printf( “ERROR example: %f\n”, x); No compile error but there is runtime error. It is not recommended to define a function with ellipses list.

Therefore, we will not cover how to define functions with ellipses list in this course.

If you really need to define a function with ellipses list, search the word “va_arg” in MSDN.

But you should know how to use it (printf) and aware it is possible to define a function with any number of parameters.

Page 88: HKUST Summer Programming Course 2008

88Department of Computer Science and Engineering, HKUST

Function

Separate Compilation (Function Level)

Page 89: HKUST Summer Programming Course 2008

89

Necessity of Separate Compilation Imagine that we have a program main.cpp that utilizes many

other functions, say sorting, searching. It is useful to keep the implementation of the sorting and

searching in separate files sort.cpp and search.cpp because: We can easily reuse the utilities in another (application) program. Team programming can be achieved easily: one teammate

implements sort.cpp, another implements search.cpp, and the last implements main.cpp. They can edit the code (in three files) concurrently.

When the sorting routines are changed, only sort.cpp needs to be compiled again (instead of recompilation of all three .cpp files), so the compilation is faster. 1 hour may be needed to compile all the code of a large software.

Page 90: HKUST Summer Programming Course 2008

90

Header files

We may not want the user (say, Peter) who writes main.cpp to know the details of the sorting routines (which can be commercial secrets), we may want to give minimal information about the sorting routines to Peter. Just gives the function declaration of sorting routines to

Peter. OR Peter may not want to read the detail implementation of

the sorting routines, which is irrelevant to his job (writing a main.cpp). Peter just want to read the function declaration of sorting

routines, instead of the function definition.

Page 91: HKUST Summer Programming Course 2008

91

Header files

Therefore, we usually separate the function definition and function declaration: Function declarations are written to a header file (.h file).

Sometimes, the header files may have extension .hpp. Function definitions are written to a source file (.cpp file).

Then, we can just give the file sort.h to Peter. This allows Peter know how to call (how many parameters, what’s

the return value, …) the function, say bubbleSort, in the main.cpp.

This also allows the compiler to determine whether there are any compilation error (invalid type of parameters, …).

Page 92: HKUST Summer Programming Course 2008

92

Compilation

After Peter finished the coding of main.cpp, he has to provide both:

main.cpp sort.h

to the compiler. This will produce an immediate object file (main.o).

But without sort.cpp, C++ don’t know the exact implementation of bubbleSort. We must somehow tell C++ how to implement bubbleSort.

Page 93: HKUST Summer Programming Course 2008

93

Linking If Peter can access the source code of sort.cpp (eg.

implemented by his teammate), he can simply gives sort.cpp to the compiler.

Otherwise, the library producer must provide a compiled object code (sort.o) to Peter. Peter can then link the sort.o with main.o (possibly link

with search.o) together. Linker is used to perform this linking.

In summary, the library producer should provides two files to Peter: sort.h (for compilation) sort.o (for linking)

Page 94: HKUST Summer Programming Course 2008

94

(Incomplete) procedure for generating executable

File1.cpp

File2.cpp

FileN.cpp

File1.o

File2.o

FileN.o

a.out

Compilation Linking

…… ……

Page 95: HKUST Summer Programming Course 2008

95Department of Computer Science and Engineering, HKUST

Function

Header Files

Page 96: HKUST Summer Programming Course 2008

96

Header Files

Recall that Function declarations are usually placed in header files (*.h). Function definition are usually placed in source files (*.cpp).

The header file can then be given to other programmers to allow calling this function. We usually add comments for the functions in header files. Other programmers can read the *.h to know what the

function does, instead of reading the *.cpp to know how the function does.

Page 97: HKUST Summer Programming Course 2008

97

Header Files

Header files can be used to store many things: Function Declaration Constant Definition Macro Definition (will be covered later …) Class Definition (will be covered later …) etc.

Page 98: HKUST Summer Programming Course 2008

98

#include Recall that there are two versions to include a header file:

#include <iostream> // standard libraries#include “utility.h” // user-defined functions

To be more precise, The first version will instruct the preprocessor to search the file

iostream from the default include directories. The second version will instruct the preprocessor to search the file

utility.h from the current directory. By default, compiler will define the default include

directories as the paths of the standard libraries. You can also overrides this or add some more additional include

directories in preprocessor setting. You may add additional include directories when you install a third-

party library.

Page 99: HKUST Summer Programming Course 2008

99

Preprocessing

To be more precise, there is a preprocessing step before the compilation. This step will be performed by the preprocessor.

The preprocessor will read all statements started with # in the first column. Never gives extra space before #include "...“.

Usually, compilation is regarded as the name of the procedure of preprocessing and then compilation. You can also view the result of preprocessed file by setting

the compiler options.

Page 100: HKUST Summer Programming Course 2008

100

(Complete) procedure for generating executable

File1.cpp

File2.cpp

FileN.cpp

File1_temp.cpp

File2_temp.cpp

FileN_temp.cpp

File1.o

File2.o

FileN.o

a.out

Preprocessing Compilation Linking

…… …… ……

Page 101: HKUST Summer Programming Course 2008

101

Preprocessing

There are a lot of preprocessor directives in C++. Some compilers will even define more directives themselves. In this course, we will cover only the following preprocessor

directives: #include #ifndef, #define, #endif

Page 102: HKUST Summer Programming Course 2008

102

#include

#include is used to copy the content of the included file to replace the line of #include. However, this may introduce compile error when a header

file includes another header file.

const int WIDTH = 99;

constants.h

#include "constants.h"

void resize(int width = WIDTH*2);

screen.h

#include "screen.h"#include "constants.h"int main( ) { resize(WIDTH); return 0;}

main.cpp

Page 103: HKUST Summer Programming Course 2008

103

#include

The preprocessor will Copy the content of screen.h to replace the line

#include “screen.h” in main.cpp Recursively copy the content of constants.h to replace

the line #include “constants.h” in screen.h Copy the content of constants.h to replace the line

#include “constants.h” in main.cpp

Page 104: HKUST Summer Programming Course 2008

104

#include

After preprocessing, the main_temp.cpp becomes

which will be inputted to the compiler.

const int WIDTH = 99; void resize(int width = WIDTH*2);const int WIDTH = 99;

int main( ) { resize(WIDTH); return 0;}

main_temp.cpp

Page 105: HKUST Summer Programming Course 2008

105

#include

Since a constant can only be defined once. The above preprocessed file will cause compile error

(WIDTH is redefined). To resolve this problem, we can use #ifndef (if not defined),

#define, and #endif #define can be used to define some symbols in

preprocessor. The code between #ifndef and #endif will be discarded by the

preprocessor if the symbol after #ifndef is defined.

Page 106: HKUST Summer Programming Course 2008

106

#ifndef, #define, and #endif

We can use #ifndef, #define, and #endif to enclose the content of header files.

#ifndef CONSTANTS_H#define CONSTANTS_H

const int WIDTH = 99;

#endif // CONSTANTS_H

constants.h#ifndef SCREEN_H#define SCREEN_H

#include “constants.h”

void resize( int width = WIDTH*2);

#endif // SCREEN_H

screen.h#include “screen.h”#include “constants.h”int main( ) { resize(WIDTH); return 0;}

main.cpp

Page 107: HKUST Summer Programming Course 2008

107

#ifndef, #define, and #endif

After including all header files, it becomes:

#ifndef SCREEN_H#define SCREEN_H#ifndef CONSTANTS_H#define CONSTANTS_Hconst int WIDTH = 99;#endif // CONSTANTS_Hvoid resize(int width = WIDTH*2);#endif // SCREEN_H#ifndef CONSTANTS_H#define CONSTANTS_Hconst int WIDTH = 99;#endif // CONSTANTS_H

int main( ) { resize(WIDTH); return 0;}

Page 108: HKUST Summer Programming Course 2008

108

#ifndef, #define, and #endif

If we further process the preprocessor directives #ifndef, #define, and #endif, we have: 2nd Line: define symbol SCREEN_H 4th Line: define symbol CONSTANTS_H 5th Line: define constant integer WIDTH 7th Line: declare the function resize 9th Line: since the symbol CONSTANTS_H is already

defined, the whole block (9th – 12th Lines) are discarded Continue to define the main function.

Page 109: HKUST Summer Programming Course 2008

109

#ifndef, #define, and #endif

The preprocessed file is:

No redefinition of constant WIDTH!!

// SCREEN_H is defined in preprocessor// CONSTANTS_H is defined in preprocessorconst int WIDTH = 99;void resize(int width = WIDTH*2);

int main( ) { resize(WIDTH); return 0;}

Page 110: HKUST Summer Programming Course 2008

110Department of Computer Science and Engineering, HKUST

Function

g++ and Makefile

Page 111: HKUST Summer Programming Course 2008

111

g++

g++ is a tool in UNIX (or Linux) to develop C++ programs. It can compile source code and link object files.

To build an executable with g++, we can:g++ main.cpp By default, this will produce an executable a.out by

compiling (and preprocessing) the single source code file main.cpp We can rename the executable with the -o option:

g++ -o myProgram main.cpp

g++ has many other options. Use man g++ for detail in Linux.

Page 112: HKUST Summer Programming Course 2008

112

g++

When there are multiple source file, we can compile them together by typing, say:

g++ sort.cpp search.cpp main.cpp This will also output a.out by default.

Page 113: HKUST Summer Programming Course 2008

113

g++ To compile (but not link) a .cpp file with g++, we can:

g++ -c main.cpp By default, this will produce an object file main.o by

compiling the source code file main.cpp We can rename the object file with the -o option

g++ -o myObjectFile.o –c main.cpp Similarly, we can:

g++ -c sort.cppg++ -c search.cpp

After producing three object files, we have to link them together:

g++ sort.o search.o main.o This will, by default, output a.out; rename with -o option.

Page 114: HKUST Summer Programming Course 2008

114

g++

Compiling the .cpp into object files separately can speed up the compilation.

A large project may contain 100000 .cpp files and build an executable may take 1 hour. A small change to the code will take another hour to compile

the whole program again. However, if we compile each .cpp into an object file, we only

need to recompile one object file and re-link the object files together, when there is a change in a .cpp file.

This significantly improve the efficiency of compilation.

Page 115: HKUST Summer Programming Course 2008

115

Makefile

Although compiling source files into multiple object files can improve the compilation efficiency, it is tedious to manage the process of compilation and linking of program code. If a single file (say search.cpp) changed, we have to

recompile the search.cpp by the command: g++ -c search.cpp

Then, we have to re-link the three object files (one of them has been updated) together by the command:g++ sort.o search.o main.o

Page 116: HKUST Summer Programming Course 2008

116

Makefile Now, imagine that the header file (sort.h) has been

changed (and we assume that main.cpp) has included the sort.h main.o must be recompiled.

Some functions guaranteed to be defined in sort.h previously may have been removed.

Without recompilation, the main.cpp may call some non-exist function and resulted in linking error (reason is on next slide).

Therefore, we have to reproduce the executable by:g++ -c sort.cppg++ -c main.cppg++ sort.o search.o main.o

To make this process easier, we can make use of Makefile.

Page 117: HKUST Summer Programming Course 2008

117

Calling non-exist function Why is it possible to call a non-exist function? For example:

If the header file declared two overloaded functions:int abs( int val );double abs( double val );

If main.cpp included this header file, the call abs( -3.2 ) will be matched to the double-version of abs (exact match).

Now, if the design is modified so that the double-version of abs has been removed, and further assume the main.cpp has not been recompiled.

The main.o contains the information that it will call the double-version of function call.

In the linking process, the linker cannot find the definition of the double-version of abs linking error resulted.

Page 118: HKUST Summer Programming Course 2008

118

Calling non-exist function

If we recompile main.cpp, the function call will now be matched to the int-version of abs (automatic conversion), no linking error will occur. Although the logic in main.cpp may most-likely need to be

changed (in this example) and resulted in a modification in main.cpp recompilation of main.cpp

Designer of Makefile should make sure the result of separate compilation should be the same as that of compiling the whole program from scratch.

Page 119: HKUST Summer Programming Course 2008

119

Makefile

Makefile is a plain text file that specifies the relationship of the program code and states the commands for updating each file. According to rules defined in the file, pieces of a large

program which need to be recompiled can be determined automatically.

For those don’t need to be re-compiled, they are just by-passed and thus avoiding redundant compilation (faster compilation).

Page 120: HKUST Summer Programming Course 2008

120

Makefile

After writing the Makefile, you can now use the tool make to produce the executable.Simply type “make” By default, make will look for the file makefile. If not found,

it will search the file Makefile, … UNIX Filesystem is case sensitive.

If your Makefile is not named as the default ones, you can use the -f option to specify your Makefile. Eg. make -f MyMakeFile

Page 121: HKUST Summer Programming Course 2008

121

A Simple Example of Makefile

myProgram: main.o search.o sort.og++ -o myProgram main.o search.o sort.o

main.o: main.cpp sort.h search.h

g++ -c main.cpp

sort.o: sort.cpp sort.h

g++ -c sort.cpp

search.o: search.cpp search.h

g++ -c search.cpp

clearAll:

rm -f *.o myProgram

Page 122: HKUST Summer Programming Course 2008

122

Explanation

Lines 1-2 forms a rule A rule has a dependency line follows by some action lines

Line 1: a dependency line that indicates the file myProgram depends on three object files main.o, sort.o and search.o

Line 2: an action line or a command that will be executed if one or more of the .o files specified in the dependency line has been modified. By comparing the modification time of the files myProgram

and *.o

Page 123: HKUST Summer Programming Course 2008

123

Explanation Action lines

There can be zero, one, or more than one action lines following a dependency line.

Each action line must begin with a tab character. It should be careful enough that tab is not equivalent to

several spaces. The general format of a rule is:

<Target>: dependencies separated by space<tab> action1<tab> action2<tab> ...

A Makefile can contain many rules.

Page 124: HKUST Summer Programming Course 2008

124

Explanation make will by default run the first rule of the Makefile.

To run a different rule, for example, make cleanAllto run the rule named cleanAll.

When “make” runs a rule, it will first examine the corresponding dependency line. If that line specify another target (rule in the Makefile), it will

run that rule first. After that, it will determine whether the file has been

modified. If no modification is found, it will stop running that rule.

Otherwise, it will run the action line’s commands.

Page 125: HKUST Summer Programming Course 2008

125

Explanation (Scenario 1) No object file and executable has been generated (at the

beginning). When we type “make”, it will run the first rule (ie. myProgram) by

default. It will scan the dependency line and found the first dependency

main.o Since main.o is another target, run the rule named main.o It will then scan the dependency line and found that the two

dependencies are not another target. It will compare the modification time of main.o and its dependencies. Since main.o do not exist, it will run the action line g++ -c main.cpp

Similarly, it will run the action lines of targets: sort.o and search.o

Then, since myProgram do not exist, it will run the action line:g++ -o myProgram main.o sort.o search.o

Page 126: HKUST Summer Programming Course 2008

126

Explanation (Scenario 2) sort.cpp has been modified after generation of all object

code. “make” will run the first rule (ie. myProgram) by default. It will scan the dependency line and found the first

dependency main.o Since main.o is another target, run the rule named main.o It will then scan the dependency line and found that the two

dependencies are not another target. It will compare the modification of main.o and its dependencies. Since main.o should have a later modification time than main.cpp,

sort.h, search.h, it will not run the action line g++ -c main.cpp to avoid duplicated compilation.

Similarly, no action will be performed for the dependency search.o

Page 127: HKUST Summer Programming Course 2008

127

Explanation (Scenario 2)

It will then encounter the dependency sort.o, it will go to the rule sort.o Since sort.cpp has been modified after sort.o is

generated, the action line g++ -c sort.cpp is performed. After that, it compares the modification time of myProgram

and *.o Since sort.o is just compiled, its modification time is later

than myProgram, hence the action line.g++ -o myProgram main.o search.o sort.o is performed to generate a new myProgram.

Page 128: HKUST Summer Programming Course 2008

128

Explanation (Scenario 3)

sort.h has been modified after generation of all object files. “make” will run the first rule (ie. myProgram) by default. It will scan the dependency line of myProgram.

Since both rules main.o and sort.o depends on the file sort.h, their action lines will be run when make is examining the dependency of the rule myProgram.

Since search.o do not depend on the file sort.h, search.o will not be recompiled.

After that, it generates a new myProgram, since the object files sort.o and main.o have just been modified.

Page 129: HKUST Summer Programming Course 2008

129

Explanation (Scenario 4)

No files have been modified after generation of all object files. “make” will run the first rule (ie. myProgram) by default. It will scan the dependency line and found the first dependency

main.o Since main.o is another target, run the rule named main.o

Since main.o is later than main.cpp, sort.h and search.h, no compilation is carried out to generate main.o

Similarly, no compilation for sort.o and search.o Since main.o, sort.o, and search.o have not been modified,

myProgram will not be re-generated.

Page 130: HKUST Summer Programming Course 2008

130

Explanation (Scenario 5)

sort.o is removed by the command “rm”. sort.o will be generated since sort.o do not exist. Re-linking main.o, sort.o and search.o to generate

myProgram, since sort.o is newly created. Although myProgram should be the same as before (no

source code has been modified).

Page 131: HKUST Summer Programming Course 2008

131

Explanation (Scenario 6)

make cleanAll is typed in the console. “make” will not run the first rule. Instead, “make” will run the rule “cleanAll” directly. Since there is no dependencies in the rule “cleanAll”, the

action line is performed automatically. It will then remove the object files *.o and myProgram.

Page 132: HKUST Summer Programming Course 2008

132

Hints for Writing Makefile By default, make will run the first rule.

Except when we call the rule directly. The first rule is for the final executable.

It depends on all object files (*.o). Each *.o will corresponds to a single rule, which is

generated by compiling a single .cpp file. The dependency list contains the source.cpp Contains all the header files it has included. Recursively find the inclusion of other header files in each

such header file. The name of each target (myProgram or *.o) is the file

name to be generated by that rule.

Page 133: HKUST Summer Programming Course 2008

133Department of Computer Science and Engineering, HKUST

Function

Function Execution in Runtime

Page 134: HKUST Summer Programming Course 2008

134

Program Call Stack When a function (say, funA) calls another function (say,

funB), the program execution is transferred to the funB. After funB is finished, the program execution should be

able to return to the next statement after the function call funB in funA.

This is usually implemented with a stack (called program call stack). A stack is a last-in-first-out data structure Data can be inserted into it (called push) Data can be removed from it (called pop) The last data inserted into it will be popped first (last-in-first-

out)

Page 135: HKUST Summer Programming Course 2008

135

Program Call Stack There is an activation record stored in the program call stack for

each function call in runtime. To store the local variables, … of that function.

For example, when the program executing funA, the topmost record in the stack will be corresponding to funA.

When funA tries to call funB, the activation record of funB will be created and pushed to the program call stack.

After funB returns, the topmost record in the stack will be popped and then the program can continue the remaining task in funA.

The bottommost record in the program call stack may be some OS program startup routines. But we usually only concerns the records corresponds to main and

all the records above only.

Page 136: HKUST Summer Programming Course 2008

136

Program Call Stack

void funA( ) { /* … */ } void funB( ) { funA( ); } void funC( ) { funA( ); funB( ); } int main( ) { funA( ); funC( ); return 0; }

main main

funA

main main

funC

main

funC

funA

main

funC

main

funC

funB

main

funC

funB

funA

main

funC

funB

main

funC

main

Page 137: HKUST Summer Programming Course 2008

137

Activation Record

This is used to store some information about an invocation of a function, including: Local variables. and many other things (COMP251).

Since the set of local variables are stored in program call stack, they will be disappeared when the function returns (record is popped out).

Page 138: HKUST Summer Programming Course 2008

138Department of Computer Science and Engineering, HKUST

Function

Static Variables in Function Definition

Page 139: HKUST Summer Programming Course 2008

139

Static Variables

Local variables are stored in activation record, which is placed in Program Call Stack. Once the function returns, its local variables will be

disappeared. Sometimes, we need to store information across multiple

calls of the function. Static variable is a variable that won’t be deleted after

function returns. It is not stored in activation record.

Page 140: HKUST Summer Programming Course 2008

140

Static Variables - Example

char* strtok(char* str, const char* delimiters){static char* nextStart = NULL;if ( str != NULL )

nextStart = str;// ...

} The line that defines nextStart will only run when the function is

first called. In the second call, the nextStart will not be re-initialized. It will keep

the value at the end of the 1st function call. You may not understand the above code, without understanding

the pointer. Read this after learning pointer.

Page 141: HKUST Summer Programming Course 2008

141Department of Computer Science and Engineering, HKUST

Function

Inline Function and its Compilation Model

Page 142: HKUST Summer Programming Course 2008

142

Function Call is Slow

Calling a function involves: Creation of activation record …

This will be expensive, especially when the function to be called consists of a few lines of code. To improve the runtime efficiency and maintain the code

reusability, C++ introduces inline function. Inline function means the function will not be really called in

runtime. Instead, it seems that the inline function are copied to the

function caller to obtain a more complicated function.

Page 143: HKUST Summer Programming Course 2008

143

Example of Inline Functionsinline int minimum( int x, int y ) {

return (x < y? x : y);}void f( ) {

cout << minimum(5,6) << endl;cout << minimum(2,1) << endl;

} The keyword inline is used to give a hint to the compiler that you

want the function to be inlined. Then, it seems that the function f is rewritten as

void f( ) {cout << (5 < 6? 5 : 6) << endl;cout << (2 < 1? 2 : 1) << endl;

} This will not call the function minimum at runtime, so it is more

efficient.

Page 144: HKUST Summer Programming Course 2008

144

Inline all functions?

Then, why don’t we inline all functions Sometimes, we cannot inline a function

More about this later (when we are talking about recursion) Therefore, it is a hint to the compiler only

Inline will copy the code to the function caller, this will increase the size of the binary (compiled code)

Tradeoff between code size and runtime efficiency

Page 145: HKUST Summer Programming Course 2008

145

Compilation Model for Inline functions

Since the compiler needs to replace the function call with the definition of the function. We have to provide the function definition to the function

caller during compilation. Instead of only providing function declaration.

Therefore, header file should include the definition of the inline functions (this is different from normal functions). For example, in utility.h

inline int minimum( int x, int y ) { return (x < y? x : y);

} In main.cpp, use the line #include “utility.h” to use

the above function.