Procedure Calls
Memory allocation, calling conventions, parameters,
environments, and cute tricks
1
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;
}
2
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.
3
Caller builds stack frame for callee
Caller starts the stack
frame for new procedure.
stack pointer
Dynamic Link
first part of stack
frame for the callee
old stack pointer
Return Address
Return value
Parameters
caller's stack frame
4
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.
5
Callee increases his stack frame
stack pointer
Callee adds space for local
variables, temporaries, and
"callee saves" register.
Locals &
Temporaries
Callee saved data
Dynamic Link
Return Address
frame pointer
Return value
Parameters
caller's stack frame
6
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)
7
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
8
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).
Simple Activation Record
(static allocation)
Stack Dynamic Activation
Record
Temporaries
Temporaries
Local variables
Local variables
Return Address
Dynamic Link
Parameters and Returns
Return Address
stack
Parameters & Returns
9
Simple Static Allocation
Both code and data areas are allocated statically.
 Early FORTRAN used this method for efficiency.

MAIN
SUB1
Data
Code
SUB2
SUB3
Locals & Temps
Return address
Parameters
Locals & Temps
Return address
Parameters
Locals & Temps
Return address
Parameters
Local variables
SUB3
SUB2
SUB1
MAIN
10
Stack Dynamic Allocation (1)

Activation records are pushed onto a stack
main() {
int a, b, c;
b = sub1(a);
c = sub2(a,b);
...
}
sub1(x) { ... }
sub2(x,y) {
...
int z = sub3();
main is
running
free
space
main calls
sub1
free
space
Local variables
sub1
main
Temporaries
main
Dynamic link
Return address
Parameters
frame pointer
11
Stack Dynamic Allocation (2)

Activation records are pushed onto the stack
main() {
int a, b, c;
b = sub1(a);
c = sub2(a,b);
...
}
sub1(x) { ... }
sub2(x,y) {
...
int z = sub3();
sub1
returns
free
space
main
main calls
sub2
free
space
sub2 calls
sub3
free
space
sub3
sub2
sub2
main
main
12
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?
13
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, SUM
DATA SUM /0.0/
SAVE SUM
SUM = SUM + X
END
PROGRAM MAIN
ACCUM(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!
14
How Can You Detect? (cont.)
Q: How can you tell if static allocation is being used?
SUBROUTINE STATIC
REAL X, SUM
DATA SUM /0.0/
IF (SUM .EQ. 1) THEN
WRITE(*,*) 'STATIC'
ENDIF
SUM = 1
END
PROGRAM MAIN
CALL STATIC
CALL JUNKSTACK
CALL 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).
15
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]
16
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() {
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
sub1
main
frame pointer
main
17
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

Stack
main() {
int a, b, c;
b = sub1(a);
c = sub2(a,b);
...
}
sub1(x) {
int u,v,w;
u =sub2(u-v,w);
Temporary
free
space
stack pointer
values
u-v
w
v
sub1
u
Dynamic link
main
Return address
Parameters
frame pointer
18
Example: GNU C on the MIPS cpu
The 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)
19
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.

20
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.
21
Activation record of p:
22
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( ): real
begin
return x*x;
end;
Function f2( ): real
var x,y: real;
begin
x := 5;
y := f1( );
return y;
end;
begin (* outer *)
x := 10;
y := f2( ); (* =? *)
23
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.
24
Nested Procedures Example (Ada)
procedure outer is
x: integer;
procedure p (y: integer) is
begin
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 ???
25
Environment during exec of p
© 2003 Brooks/Cole - Thomson Learning™
26
"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
27
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;
}
}
28
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.
29
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 */
param2 = 20
swap
param1 = 10
Dynamic link
Return address
main
y = 20
x = 10
30
Call by Reference

Advantages:



avoids time & space overhead of copying data structures
programmer can return results using parameters
Disadvantages:


int main() {
int x = 10, y = 20;
swap(x, y);
/* changed!
x == 10, y == 20 */
param2
swap
param1
Dynamic link
Return address
main
y = 20
x = 10
points to storage addr.
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
31
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 */
param2 = 20
swap
param1 = 10
Dynamic link
Return address
main
y = 20
x = 10
32
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));
double v = SQUARE(x++);
// sin(x) is called twice
// v = (x++)*(x++) = 2
// now x = 3.
33
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( ) {
initialize
fun( arguments );
analyze and print
conclusion.
void fun( params ) {
}
34
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.

35
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 array
int sumdata( int count,
int x[ ] ) {
int k, sum=0;
for(k=0; k<count; k++)
sum += x[k];
// declare x as pointer
void sumdata( int count,
int *x ) {
int k=0, sum = 0;
while(k++ < count) {
sum += *x;
x++;
}
increment x to point to next array
element.
36
Parameter Passing Methods in
Major Languages
37
Fortran
Fortran usually uses call by reference.
 some implementations use call by value-result for
simple parameters.

SUBROUTINE SWAP(A,B)
REAL A, B, TEMP
TEMP = A
A = B
B = TEMP
RETURN
END
PROGRAM MAIN
REAL X, Y
X = 10.0
Y = 20.0
CALL SWAP(X, Y)
! now X=20, Y=10
38
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 Main
REAL X, Y
X = 10.0
CALL SWAP(X, 5.0)
! 5.0 was changed to 10.0
Y = 2.0*5.0
! Y is 20.
SUBROUTINE SWAP(A,B)
REAL A, B, TEMP
TEMP = A
A = B
B = TEMP
RETURN
END
39
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 caller
n = n + 1000;
}
int main() {
int a = 0;
sub1(&a);
// now a == 1000
40
Call by Value in C
int main() {
int x = 10, y = 20;
swap(x, y);
/* no change!
x == 10, y == 20 */
int n = 0;
scanf("%d", n);
/* no change! n = 0
*/
void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
int n = 0;
scanf("%d", &n);
/* n changed!
*/
41
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;
}
In C, to emulate call by reference use pointers to args.
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;
}
42
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 zero
for(int k=0; k<x.length; k++) x[k] = 0;
// this also sets caller's array to all zero
Arrays.fill( x, 0);
// this has no effect on the caller's argument
x = new int[100];
// no effect on caller (anonymous array)
x = new int[] { 0, 0, 0, 0, 0 };
}
43
Parameter Passing in C++
Parameters can be passed by value or reference
 C++ uses "&" (reference) on formal parameter type.

// C/C++ pass by value
void swap(int a, int b)
{ int temp;
temp = a; a = b;
b = temp;
}
// C++ pass by ref
void 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! */
int main() {
int n = 10, m = 20;
swap(n, m);
/* n, m swapped! */
44
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
}
45
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];
}
// What is constant?
void test2(int* const b)
{ *b = *b + 1;
b = new int[100];
}
int main() {
int x[20];
test1(x);
int main() {
int x[20];
test2(x);
46
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;
}
47
Parameter Passing in C#
Parameters can be passed by value or reference
 C# uses "ref" (reference) on formal parameter type.

// C# pass by value
void 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 ref
void 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! */
48
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

type
RealArray = 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
}
49
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;
50
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.

type
RealArray = array[1..1000] of real;
Procedure Invariant( const n: integer;
const a: RealArray ) {
n and a may not be modified here
n is probably passed by value
a is always passed by reference
}
http://www.freepascal.org
http://www.freepascal.org/docs-html/ref/ref.html
51
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 reference
public int readdata( ref int [] x ) { ... }
// call by value
public int sumdata( int [] x ) { ... }
// output only parameter
public void countdata( int [] x, out int count )
{...}
52
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 is
x, y: integer;
begin
x := 10;
DoubleVal( y, x );
-- OK: y is 20
DoubleVal( x, x );
-- x still has value 10
procedure DoubleVal(
a: in out integer;
b: in out integer) is
-- double the value of b
begin
a := 2*b;
end DoubleVal;
Is this a logic error?
53
Programming Tricks with Procedures
Inline functions
 Optional parameters
 Variable length parameter lists
 Templates

54
Inline Expansion

C, FORTRAN, and others support inline expansion of
functions: entire function code is copied into each
occurrence of function call.
// 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
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.
55
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 expansion
Stack(int n) {maxsize = n; stackptr = new int[n];}
int pop();
}
// function defined outside of class: not inline
int Stack::pop() { return *top--; }
56
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 parameters
double 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);
57
Default Parameters: C++ example
Useful for functions that have infrequently used options:
// rotate and scale point (x,y), default 90-degrees
void 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 can be invoked any of these ways:
rotate(x, y);
rotate(x, y, -30.);
rotate(x, y, 45., 0.5);
// rotate 90 degrees
// rotate -30 degrees
// rotate 45, scale by 0.5
58
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.

59
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 parameter
va_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--;
must specify type
}
// va_end cleans up
va_end(argptr);
return total;
60
}
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 work
while ( (xnext = va_arg(argptr, double)) != null )
total += xnext;
61
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);
}
62
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
}
63
Generic Procedures and Classes
Ada and C++ provide syntax to generate a procedure or class of any
type, as needed.
// generic "max" function
template<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; // angle
double 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; }
64
Generic Classes
C++ template can define classes. Must instantiate explicitly.
template<class T, int maxsize = 100>
class Stack {
private:
optional template parameter
T items[maxsize];
int top;
public:
Stack( ) { top = -1; } // empty
void 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
65
Vocabulary Question
Q: What do you call a family of methods which have the
same name but different parameter types? I.e.
Arrays.sort(
Arrays.sort(
Arrays.sort(
Arrays.sort(
...
int [ ] x );
float [ ] x );
char [ ] x );
Object [ ] obj );
A: _______________
Q: Redefining "+" for strings: string = string1 + string2; is
called operator _____________ .
66
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);
}
67
Descargar

Chapter 8 - Control II: Procedures and Environments