67
1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

Embed Size (px)

Citation preview

Page 1: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

1

Procedure Calls

Memory allocation, calling conventions, parameters, environments, and cute tricks

Page 2: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

2

Procedure calls

How can one function (procedure) "call" another one?

How can we pass parameter values?

How can we return a result?

Each procedure requires its own environment and may call other procedures

May be many call points

main() {int a, b, c;b = sub1(a);c = sub2(a,b);...

}int sub1(x) {

int z = (x+1)/x;return sqrt(z);

}sub2(x,y) { int z = sub1(y);

return x + y*z;}

Page 3: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

3

Calling Sequence: caller

What must be done when a procedure is invoked?

Before Call, the caller does:

1. allocate space for a return value, if there is one

2. put return address into a known location

3. prepare actual parameter values for formal parameters

4. save any variables held in registers back to memory

5. maybe save other registers (depends on calling convention)

6. execute a "jump" instruction to the callee's code

Not necessarily in this order.

Page 4: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

4

Caller builds stack frame for callee

Caller starts the stack frame for new procedure.

Dynamic Link

Return value

Return Address

Parameters

caller's stack frame

first part of stack frame for the callee

stack pointer

old stack pointer

Page 5: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

5

Calling Sequence: callee

When a procedure (callee) is invoked, it does:

1. allocates space for its local variables and temps

2. saves any registers that it needs, if required.

3. adjust the frame pointer and stack pointer (in a stack based environment)

By convention, the callee does most of the work in the calling sequence. There are two reasons:

1. there may be many call points to a single procedure. Any instructions done on the caller's side must be duplicated at each call point, making the program larger.

2. the callee knows what registers it will use and how much stack space it needs, so callee should be responsible for saving/restoring registers and managing stack space.

Page 6: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

6

Callee increases his stack frame

Callee adds space for local variables, temporaries, and "callee saves" register. Dynamic Link

Return value

Return Address

Parameters

caller's stack frame

Locals & Temporaries

Callee saved data

stack pointer

frame pointer

Page 7: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

7

Calling Sequence: on return

When a procedure "returns" (Epilog): save any persistent (static) local variables that are in

registers if there is a return value, put it in a specified location free storage used by callee's local variables & temps restore any saved registers branch to a return address (next instruction of caller)

Page 8: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

8

Calling Sequence: example

save value of a to its memory location

save registers and P.C. put values for sub's

parameters on the stack put return address on

stack add dynamic link to

caller's stack frame branch to sub sub allocates space for x

int a; /* global */int sub( u, v ) {

if ( v == 0 )return u;

int x = u % v;return x;

}

int caller( ) {a = readInt();result =

sub(4+a*a*a, a);

temporary value

Page 9: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

9

Activation Record

Activation record or frame of a procedure is a block of memory used for parameter values, return address, local variables, temporary results, and bookkeeping (dynamic link, static link).

Temporaries

Local variables

Return Address

Parameters and Returns

Temporaries

Local variables

Dynamic Link

Parameters & Returns

Simple Activation Record (static allocation)

Return Address

Stack Dynamic Activation Record

stack

Page 10: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

10

Simple Static Allocation

Both code and data areas are allocated statically. Early FORTRAN used this method for efficiency.

MAIN

SUB1

SUB2

SUB3

Code

Local variables

Return address

Parameters

Locals & Temps

Locals & Temps

Locals & Temps

Data

MAIN

SUB1

SUB2

SUB3

Return address

Parameters

Return address

Parameters

Page 11: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

11

Stack Dynamic Allocation (1)

Activation records are pushed onto a stack

main

main is running

main calls sub1

main

sub1

main() {int a, b, c;b = sub1(a);c = sub2(a,b);...}sub1(x) { ... }sub2(x,y) { ... int z = sub3();

free space

free space Temporaries

Local variables

Return address

Dynamic link

Parameters

frame pointer

Page 12: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

12

Stack Dynamic Allocation (2)

Activation records are pushed onto the stack

main

sub1 returns

main calls sub2

main

sub2

main() {int a, b, c;b = sub1(a);c = sub2(a,b);...}sub1(x) { ... }sub2(x,y) { ... int z = sub3();

free space

free space

sub2 calls sub3

main

sub2

free space

sub3

Page 13: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

13

Comparison of Static & Dynamic Alloc

Advantages of Static Allocation addresses of local vars are known at compile/load time.

This makes addressing more efficient. instructions to implement procedure calls are simpler simplifies saving of local data between calls

Advantages of Dynamic Allocation needed to implement recursion uses less memory other?

Page 14: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

14

How Can You Detect Static Allocation? Originally FORTRAN used static allocation.

Fortran "SAVE" statement was superfluous! Now some implementations use stack dynamic

allocation, even for Fortran 77.

Q: How can you tell if static allocation is being used?

SUBROUTINE ACCUM(X)REAL X, SUMDATA SUM /0.0/SAVE SUMSUM = SUM + XENDPROGRAM MAINACCUM(1.0)ACCUM(2.5)...etc...

"SAVE" means that the value of this local variable should be saved between calls, i.e. static allocation.

However, in FORTRAN IV all local variables were static!

Page 15: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

15

How Can You Detect? (cont.)

Q: How can you tell if static allocation is being used?

SUBROUTINE STATICREAL X, SUMDATA SUM /0.0/IF (SUM .EQ. 1) THEN WRITE(*,*) 'STATIC'ENDIFSUM = 1ENDPROGRAM MAINCALL STATICCALL JUNKSTACKCALL STATIC...etc...

DATA SUM /0.0/ initializes SUM to 0.

In a static environment, this is done only once, so second time, the value of SUM will be 1.

JUNKSTACK is some other procedure that puts junk in local variables, to change the old contents of the stack (if dynamic allocation).

Page 16: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

16

Why use the stack?

Many lexically typed languages use the stack for parameter values, local variables, temps, etc.

Why use stack instead of registers? Observation by Michael Scott:

The use of the stack to pass arguments reflects the technology of the 1970s, when register sets were significantly smaller and memory access was significantly faster (in comparison to processor speed). [Programming Language Pragmatics, p. 438]

Page 17: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

17

Frame Pointer In stack dynamic allocation, the actual addresses of

data on the stack aren't known at compile time. Addresses are given relative to a frame pointer (fp), or

environment pointer (ep), usually kept in a register.

main main

sub1

main() {int a, b, c;b = sub1(a);c = sub2(a,b);...}sub1(x) {int u,v,w; u =sub2(u-v,w);

free space

free space

frame pointer

Page 18: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

18

Frame Pointer (2) For example, addresses of the local variables u, v, w might be referred

to as: (fp)+8, (fp)+12, (fp)+16 This is called displacement addressing

main

sub1

main() {int a, b, c;b = sub1(a);c = sub2(a,b);...}sub1(x) {int u,v,w; u =sub2(u-v,w);

free space

frame pointer

StackTemporary

values

u-v

u

Return address

Dynamic link

Parameters

v

w

stack pointer

Page 19: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

19

Example: GNU C on the MIPS cpuThe MIPS cpu is a RISC processor with 32 general registers (r0 - r31) and several floating point registers (f0 - ...).

Registers are divided into 2 groups:

caller-saves registers: caller is responsible for saving any values in these registers. The callee can use these without saving old value.

callee-saves registers: callee is responsible for saving/restoring values in these registers before/after using them.

The compiler uses callee-saves registers for local variables and other long-lived items, and uses caller-saves registers for transient values such as loop indices. This minimizes "register saves" overhead in procedure calls.

Registers are used for special values:

r31 = return address r4-r7 = first 4 scalar parameters

r30 = frame pointer (or f12-f15 for f.p. parameters)

r29 = stack pointer

Page 20: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

20

Languages and Environments

Languages differ on where activation records reside:

Static allocation: Fortran (before Fortran 90): all data, including activation

records, are statically allocated. Heap-oriented:

dynamically typed and functional languages: Scheme, ML, Smalltalk. Almost all data, including activation records, are allocated on heap.

Multiple areas: statically typed languages (C, Pascal, Algol, ...):

activation records on stack, data can be anywhere.

Page 21: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

21

Example in C

int x;void p( int y) { int i = x; char c; ...}void q ( int a) { int x; p(1);}main( ) { q(2); return 0;}

Show the contents of the stack when p is activated.

Page 22: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

22

Activation record of p:

Page 23: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

23

Nested Procedures

Some languages allow procedures to be nested inside other procedures.

Pascal and Ada are examples

Inner procedure is "known" only in the scope of outer procedure.

Inner procedure can access variables of the outer procedure (static scope rules).

Procedure outer(p: real)var x, y: real;begin

Function f1( ): realbegin

return x*x;end;Function f2( ): realvar x,y: real;begin

x := 5;y := f1( );return y;

end;begin (* outer *)

x := 10;y := f2( ); (* =? *)

Page 24: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

24

Nested Procedures and non-local variables

active procedure needs to be able to locate the frame of lexically enclosing scopes ("parent" scope).

Outer procedure must be somewhere on the stack, but it may be buried far below the current frame.

The lexically enclosing procedure must be on the stack, because "inner" procedure can only be called from within the "outer" procedure.

To find the lexically enclosing scope, we need another pointer -- called the static link or access link.

Page 25: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

25

Nested Procedures Example (Ada)

procedure outer is x: integer;

procedure p (y: integer) isbegin

return y * x;end p;procedure r(a: integer) is x: float;begin p(a); ...

end r;begin r(1);end q;

Where is x ???

Page 26: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

26© 2003 Brooks/Cole - Thomson Learning™

Environment during exec of p

Page 27: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

27

"Closure"

A reference to a procedure along with its referencing environment is called a "closure".

Closures are important in languages that allow functions to be arguments or values of variables.

int main( ) {double a = 10, b = 3;double x = 0.5; dy = deriv( fun, x );

double fun(x) {return a*x + b;

}}

/* procedure that has a * function as parameter */double deriv( f, x) {

double a = 1, b = 2;double df;double dx = 1.0E-6;df = (f(x+dx)-f(x))/dx;

}

needs values of a and b

Page 28: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

28

Two Methods for Factorial

In a stack dynamic environment, which is more efficient?

int factorial(int n) {if ( n <= 1 ) return 1;return n*factorial(n-1);

}

int factorial(int n) {int fact = 1;while( n > 1 ) {

fact = fact * n;n = n - 1;

}}

Page 29: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

29

Parameter Passing Methods

Call by value: actual parameter values are copied into location of formal parameters.

Call by reference: a reference to the storage location of calling argument is passed to parameter.

Call by value-result: actual parameter values are copied to location of formal parameters; on return the procedure's parameter values are copied back to location of calling arguments.

Call by name: parameters are evaluated in the caller's environment every time they are accessed within a procedure.

Page 30: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

30

Call by Value

Advantages: variables can be accessed directly in callee's stack frame prevents side-effects

Disadvantages: time-consuming to copy large data structures. requires additional memory for copy. cannot return a value by means of parameters -- but for reference

data types you can change what the param points to

int main() {int x = 10, y = 20;swap(x, y);/* no change!

x == 10, y == 20 */

Dynamic link

y = 20

Return address

x = 10

param1 = 10

param2 = 20

main

swap

Page 31: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

31

Call by Reference

Advantages: avoids time & space overhead of copying data structures programmer can return results using parameters

Disadvantages: can cause accidental side effects; can produce aliases access to formal parameters is slower (for simple data types)

since callee must access value indirectly through address

int main() {int x = 10, y = 20;swap(x, y);/* changed!

x == 10, y == 20 */

Dynamic link

y = 20

Return address

x = 10

param1

param2

main

swap

points to storage addr.

Page 32: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

32

Call by Value-Result

Advantages: programmer can return results using parameters direct (offset) addressing of formal parameters

Disadvantages: requires extra time and stack space to copy values results may depend on the order that values are copied

int main() {int x = 10, y = 20;swap(x, y);/* change!

x == 20, y == 10 */

Dynamic link

y = 20

Return address

x = 10

param1 = 10

param2 = 20

main

swap

Page 33: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

33

Call by Name

computationally expensive and inefficient due to need to re-evaluate formal parameters for each access.

not used in any mainstream languages C pre-processor macros mimic behavior of call by

name

#define SQUARE(X) ((X)*(X))

int main() {double x = 1.0;double u = SQUARE(sin(x)); // sin(x) is called

twicedouble v = SQUARE(x++); // v = (x++)*(x++) = 2

// now x = 3.

Page 34: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

34

Exercise: call by what?

Describe how you could determine whether parameters to a procedure were passed by reference, value, or value-result.

Write a short C or C++ program to illustrate the idea.

int main( ) {initializefun( arguments );analyze and printconclusion.

void fun( params ) {

}

Page 35: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

35

Passing an Array as Parameter (1)

When we pass an array as parameter, what value(s) are passed?

For example, in C:int main( ) {

int x[100];readdata(100, x);sumdata(100, x);

void readdata(int count,int x[ ] ) {

x[1] = 10;}

In C, an array variable is a reference (pointer) to the start of the array.

Only the array address (4 B) is passed as parameter.

Page 36: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

36

Passing an Array as Parameter (2)

This explains why a function can change the values of array elements, even though C uses call by value.

Both of these codes are equivalent:// declare x as arrayint sumdata( int count,

int x[ ] ) {int k, sum=0;for(k=0; k<count; k++)

sum += x[k];

// declare x as pointervoid sumdata( int count,

int *x ) {int k=0, sum = 0;while(k++ < count) {

sum += *x;x++;

}

increment x to point to next array element.

Page 37: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

37

Parameter Passing Methods inMajor Languages

Page 38: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

38

Fortran

Fortran usually uses call by reference. some implementations use call by value-result for

simple parameters.

SUBROUTINE SWAP(A,B)REAL A, B, TEMPTEMP = AA = BB = TEMPRETURNEND

PROGRAM MAINREAL X, YX = 10.0Y = 20.0CALL SWAP(X, Y)! now X=20, Y=10

Page 39: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

39

Call by Reference: Fortran Bug

Fortran uses call by reference In some early implementations, literal constants are

stored in a (shared) static memory location. Some early compilers would change the value of a

numeric constant that was used as parameter!

Program MainREAL X, YX = 10.0CALL SWAP(X, 5.0)! 5.0 was changed to 10.0Y = 2.0*5.0! Y is 20.

SUBROUTINE SWAP(A,B)REAL A, B, TEMPTEMP = AA = BB = TEMPRETURNEND

Page 40: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

40

C and Java

C and Java always pass parameters by value. sometimes it appears to pass by reference when

passing a variable of reference type (Java), or a pointer (C).

void sub1(int *n) {// change arg to 1000*n = 1000;// this has no effect// on the callern = n + 1000;

}

int main() {int a = 0;sub1(&a);// now a == 1000

Page 41: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

41

Call by Value in C

int main() {int x = 10, y = 20;swap(x, y);/* no change!

x == 10, y == 20 */

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

}

int n = 0;scanf("%d", n);

/* no change! n = 0 */

int n = 0;scanf("%d", &n);

/* n changed! */

Page 42: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

42

Swap that works!

int main() {int x = 10, y = 20;swap(x, y);/* no change!

x == 10, y == 20 */

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

}

int main() {int x = 10, y = 20;swap( &x, &y );/* changed!

x == 20, y == 10 */

void swap(int* a, int* b) {

int temp = *a;*a = *b;*b = temp;

}

In C, to emulate call by reference use pointers to args.

Page 43: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

43

Array parameters in C and Java

In C an array name is passed as a pointer; in Java an array name is a reference to array object.

In both C and Java, a procedure can change the elements of an array. But not the array reference.

public void zero( int [] x ) {// this sets the caller's array to all zerofor(int k=0; k<x.length; k++) x[k] = 0;// this also sets caller's array to all zeroArrays.fill( x, 0);// this has no effect on the caller's argumentx = new int[100];// no effect on caller (anonymous array)x = new int[] { 0, 0, 0, 0, 0 };

}

Page 44: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

44

Parameter Passing in C++

Parameters can be passed by value or reference C++ uses "&" (reference) on formal parameter type.

// C/C++ pass by valuevoid swap(int a, int b){ int temp;

temp = a; a = b;b = temp;

}

int main() {int n = 10, m = 20;swap(n, m);/* no effect! */

// C++ pass by refvoid swap(int& a, int& b){ int temp;

temp = a; a = b;b = temp;

}

int main() {int n = 10, m = 20;swap(n, m);/* n, m swapped! */

Page 45: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

45

const Parameters in C and C++

C/C++ supports "const" for read-only parameters, which is enforced by compiler.

function may not change the value of const parameters.

void test1(const int num){

num = num + 1; // compile time error}

Page 46: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

46

const Parameters in C and C++

"const" are most useful for reference, array, and pointer types.

Syntax is detailed, as shown here.

// What is constant?void test1(const int *a){ *a = *a + 1;

a = new int[100];}

int main() {int x[20];test1(x);

// What is constant?void test2(int* const b){ *b = *b + 1;

b = new int[100];}

int main() {int x[20];test2(x);

Page 47: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

47

Limitation of const Parameters

What if a function has a "const" parameter, but passes it to another function that doesn't declare "const"?

compiler cannot verify that "const" attribute is honored

int sum( int count, const int x[ ] ) {int result = sum2(count, x);

}

// sum2 doesn't declare x as "const"int sum2( int count, int x[ ] ) {

int total = 0;while(count>0) total += x[--count]; return total;

}

Page 48: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

48

Parameter Passing in C#

Parameters can be passed by value or reference C# uses "ref" (reference) on formal parameter type.

// C# pass by valuevoid swap(int a, int b){ int temp;

temp = a; a = b;b = temp;

}

int main() {int n = 10, m = 20;swap(n, m);/* no effect! */

// C# pass by refvoid swap(ref int a,

ref int b){ int temp;

temp = a; a = b;b = temp;

}

int main() {int n = 10, m = 20;swap(ref n, ref m);/* n, m swapped! */

Page 49: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

49

Parameter Passing in Pascal

Pascal has both call by value is default: copy parameter to stack call by reference: specify using "var" keyword

Call by value is inefficient for large parameters

typeRealArray = array[1..10000] of real;

Procedure PassByValue( n: integer, a: RealArray ) {n and a are copies of caller's arguments

}Procedure PassByReference( var n: integer;

var a: RealArray ) {n and a are passed by reference

}

Page 50: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

50

Array as Parameter in Pascal An array is passed by...

call by value: copy the entire array onto stack! call by reference: copy address of array onto stack.

(* pass by value: copy the ENTIRE array to stack *)procedure sumdata( x: array[1..100] of int ): int;var k, sum: int;begin

sum :=0;for k := 1 to 100 do sum := sum + x[k];return sum;

end;

(* pass by reference: copy array address to stack *)procedure sumdata( var x: array[1..100] of int ): int;

Page 51: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

51

const Parameters in Pascal

Freepascal allows "const" parameters that cannot be assigned to (modified) inside the procedure.

Compiler will use call by value for small data (4 bytes or less), call by reference for larger parameters.

typeRealArray = array[1..1000] of real;

Procedure Invariant( const n: integer;const a: RealArray ) {n and a may not be modified heren is probably passed by valuea is always passed by reference

}

http://www.freepascal.orghttp://www.freepascal.org/docs-html/ref/ref.html

Page 52: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

52

Parameters in C#

Default is call by value. "ref" to call by reference (like Algol). "out" for output parameters (must assign before using)

// call by referencepublic int readdata( ref int [] x ) { ... }

// call by valuepublic int sumdata( int [] x ) { ... }

// output only parameterpublic void countdata( int [] x, out int count ) {...}

Page 53: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

53

Ada: many choices Parameters can be declared as "in", "out", or "in out" Compiler checks the usage of "in" and "out" vars. Language definition was ambiguous where "in out" is call by

reference or call by value-result.

procedure main isx, y: integer;

beginx := 10;DoubleVal( y, x );-- OK: y is 20DoubleVal( x, x );-- x still has value 10

procedure DoubleVal(a: in out integer;b: in out integer) is

-- double the value of bbegin

a := 2*b;end DoubleVal;

Is this a logic error?

Page 54: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

54

Programming Tricks with Procedures

Inline functions Optional parameters Variable length parameter lists Templates

Page 55: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

55

Inline Expansion C, FORTRAN, and others support inline expansion of functions: entire function code is copied into each

occurrence of function call.

Advantage: avoids overhead of function call Disadvantage: makes code larger. Not recursive.

In C, "inline" suggests that compiler use inline expansion. Compiler may ignore this request, or may "inline" functions not declared as inline.

// C example:inline double sqr(double x) { return x*x; }int main( ) {

double a, b, y;a = 10; b = 0.1;y = sqr(a - b); // sqr( ) is expanded inline

Page 56: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

56

Inline Expansion (2)

C++ usually "inlines" constructors and functions defined inside the class.

// C++ example:class Stack {private:

int maxsize;int *top = NULL; int *stackptr;

public:// candidate for inline expansionStack(int n) {maxsize = n; stackptr = new int[n];}int pop();

}// function defined outside of class: not inlineint Stack::pop() { return *top--; }

Page 57: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

57

Default (Optional) Parameters

Ada, C/C++, Fortran, etc., allow default parameters. Any parameters omitted from procedure call will be given

default values. Default parameters must be at the end of parameter list, to

avoid ambiguity. In C/C++ use:

// norm of a vector: can have 1 to 3 parametersdouble norm(double x, double y=0, double z=0) {

return sqrt( x*x + y*y + z*z ); }// calling sequences:r1 = norm( sin(0.5) );r2 = norm( 3.0, 4.0 );r3 = norm( 3.0, 4.0, -5.0);

Page 58: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

58

Default Parameters: C++ example

rotate can be invoked any of these ways:

// rotate and scale point (x,y), default 90-degreesvoid rotate(double &x, double &y,

double angle=90, double scale=1.0) {angle = angle*PI/180;double xr = x*cos(angle) - y*sin(angle); double yr = x*sin(angle) + y*cos(angle);x = xr*scale;y = yr*scale;

}

rotate(x, y); // rotate 90 degreesrotate(x, y, -30.); // rotate -30 degreesrotate(x, y, 45., 0.5); // rotate 45, scale by 0.5

Useful for functions that have infrequently used options:

Page 59: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

59

Variable Parameter Lists

C/C++ and Visual Basic have a mechanism for variable length argument lists.

Example: printf( ) and scanf( ) accept any number and type of arguments:

printf("turn %s and go %d meters", dir, distance);

printf("%8f %8f %8f", x, y, z); The first parameter (format) is used to determine

how many and what type of arguments to expect. If location of first parameter (on the stack) is known,

then remaining parameters must come after that.

Page 60: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

60

Variable Length Parameters in C (1)

In C/C++ use varargs for variable length parameters.

// function to sum any number of values#include <stdarg.h>double sum(int n, ...){ double total = 0.0;

va_list argptr;// call va_start with address of the last known parameterva_start(argptr, &n);// Each call to va_arg returns next argument on the stack. while(n>0) {

total = total + va_arg(argptr, double);// va_arg increments argptr each time.n--;

}// va_end cleans up

va_end(argptr);return total;

}

must specify type

Page 61: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

61

Variable Length Parameters in C (2) Why do we need to know the number of parameters?

Can varargs determine number of params itself? What happens if we read beyond the next of parameter list (call

va_arg( ) too many times)? Can we determine the type of the next argument on the stack?

// function to sum any number of values#include <stdarg.h>double sum(double x, ...) // no arg counter!!{ double total, xnext;

va_list argptr;total = x;va_start(argptr, &x);// get all parameters: this doesn't workwhile ( (xnext = va_arg(argptr, double)) != null )

total += xnext;

Page 62: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

62

The Problem with varargs

varargs is not type safe. Compiler cannot check that argument type matches

expected data type No run-time type checking. A function can...

assign wrong data type to an argument read beyond end of arguments

Simple example:

void sub1(double a, int b, double c) {

// use wrong format -- printf will expect

// arguments to match the formats

printf("sub1: %d %f %d %ud %ud\n", a, b, c);

}

Page 63: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

63

Variable Arguments in Java

Java 1.5 has variable arguments. Variable part must be at the end of parameter list. Type safe. Used by printf and format.

/* Better println : can print any number of objects! */

public static void println( Object ... arg ) {

// arg is an array of type Object.

// Use arg.length to determine number of args.

for(int k=0; k < arg.length; k++)

System.out.print( arg[k] );

System.out.println( ); // newline after last one

}

Page 64: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

64

Generic Procedures and Classes

Ada and C++ provide syntax to generate a procedure or class of any type, as needed.

// generic "max" functiontemplate<typename T> // or: template<class T>T max(T a, T b) { if (a > b) return a; else return b; }

The compiler instantiates this function only when it is needed. If your code contains:

double t = 0.6; // angledouble y = max(cos(t), sin(t));

The compiler will generate and compile:

double max(double a, double b){ if (a > b) return a; else return b; }

Page 65: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

65

Generic Classes

C++ template can define classes. Must instantiate explicitly.

template<class T, int maxsize = 100>class Stack {private:

T items[maxsize];int top;

public:Stack( ) { top = -1; } // emptyvoid push(T value) {

if (top<maxsize-1) { items[++top] = value; }else throw( StackError );

}T pop( ) { if (top>=0) return items[top--];

else throw( StackError );}...

}Stack<string, 50> stringstack; // create an object

optional template parameter

Page 66: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

66

Vocabulary Question

Q: What do you call a family of methods which have the same name but different parameter types? I.e.

Arrays.sort( int [ ] x );

Arrays.sort( float [ ] x );

Arrays.sort( char [ ] x );

Arrays.sort( Object [ ] obj );

...

A: _______________

Q: Redefining "+" for strings: string = string1 + string2; is called operator _____________ .

Page 67: 1 Procedure Calls Memory allocation, calling conventions, parameters, environments, and cute tricks

67

Can an Application Detect the Parameter Passing Mechanism?

Q: What values will be printed using "pass by value", "pass by reference", and "pass by value-return"?

// What parameter passing mechanism?void CallByWhat(int& n, int& m) {

n++;if (n == m) printf("CallByWhat: identical\n");else printf("CallByWhat: not identical\n");m++;

}int main() {

int a = 0;CallByWhat( a, a);printf("main: a = %d\n", a);

}