Transcript Parameters

Parameter Passing
CMSC 331
Extracted with only very minor changes from
http://www.itk.ilstu.edu/faculty/chungli/ITK327/Parameters.ppt
Parameter Passing
formal parameters
int plus (int a, int b)
{
return a+b;
}
int x = plus(1,2);
function
body
actual parameters
(arguments)
function call



7/7/2015
How are parameters passed?
Looks simple enough…
We will see seven techniques
7 methods for passing parameters
By value
By result
By value-result
By reference
By macro expansion
By name
By need
7/7/2015
3
What’s wrong?
int * sum (int & a, int & b)
{
int sum;
sum = a + b;
return & sum;
}
int * sum (int & a, int & b)
{
a += b;;
return a;
}
7/7/2015
int * sum (int & a, int &
b)
{
a += b;
return & a;
}
int a, b, *c;
a=1;
b=2;
c = sum(a,b);
4
Parameter Correspondence


Which actual parameters go to
which formal parameters?
Most common case: positional
parameters


7/7/2015
Correspondence determined by
positions
nth formal parameter matched with nth
actual
5
Keyword Parameters

Determined by matching parameter names
Ada:
DIVIDE( DIVIDEND => X, DIVISOR => Y);
DIVIDE( DIVISOR => Y, DIVIDEND => X);
Parameter order is irrelevant here
7/7/2015
6
Mixed Keyword And Positional


7/7/2015
Most languages that support
keyword parameters allow both:
Ada, Fortran, Dylan, Python
The first parameters in a list can be
positional, and the remainder can
be keyword parameters
7
Optional Parameters

Default values: formal parameter list includes
default values to be used if the corresponding
actual is missing
int f(int a=1, int b=2, int c=3) { body }
int x=f(), y=f(0), z=f(0,0), h=f(0,0,0);
Same as Overloading:
int
int
int
int
7/7/2015
f() {f(1,2,3);}
f(int a) {f(a,2,3);}
f(int a, int b) {f(a,b,3);}
f(int a, int b, int c) { body }
8
Unlimited Parameter Lists



Some languages allow actual parameter
lists of unbounded length: C, C++, and
scripting languages like JavaScript, Python,
and Perl
Library routines must be used to access the
excess actual parameters
A hole in static type systems, since the
types of the excess parameters cannot be
checked at compile time
int printf(char *format, ...) { body }
7/7/2015
9
Call By Value
For by-value parameter passing, the formal parameter
is just like a local variable in the activation record of
the called method, with one important difference: it is
initialized using the value of the corresponding actual
parameter, before the called method begins executing.



Or not!
Simplest method
Widely used
The only method in Java!!!!
Java is Pass-By-Value, Dammit!
7/7/2015
10
int plus(int a, int b) {
a += b;
return a;
}
void f() {
int x = 3;
int y = 4;
int z = plus(x, y);
}
When plus
is starting
7/7/2015
current
activation record
plus(3,4)
f()
a: 3
x: 3
b: 4
y: 4
return address
z: ?
previous
activation record
return address
result: ?
previous
activation record
11
By Result
For by-result parameter passing, the formal parameter
is just like a local variable in the activation record of
the called method—it is uninitialized. After the called
method finished executing, the final value of the
formal parameter is assigned to the corresponding
actual parameter.



7/7/2015
Also called copy-out
Actual must have an lvalue
Introduced in Algol 68; sometimes
used for Ada
12
void plus(int a, int b, by-result int c) {
c = a+b;
}
void f() {
int x = 3;
int y = 4;
current
int z;
activation record
plus(x, y, z);
plus(3,4,z)
}
When plus
is starting
7/7/2015
f()
a: 3
x: 3
b: 4
y: 4
c: ?
z: ?
return address
return address
previous
activation record
previous
activation record
13
void plus(int a, int b, by-result int c) {
c = a+b;
}
void f() {
int x = 3;
int y = 4;
current
int z;
activation record
plus(x, y, z);
plus(3,4,z)
}
When plus is
ready to return
7/7/2015
f()
a: 3
x: 3
b: 4
y: 4
c: 7
z: ?
return address
return address
previous
activation record
previous
activation record
14
void plus(int a, int b, by-result int c) {
c = a+b;
}
void f() {
int x = 3;
int y = 4;
current
int z;
activation record
plus(x, y, z);
f()
}
When plus
has returned
7/7/2015
a: 3
x: 3
b: 4
y: 4
c: 7
z: 7
return address
return address
previous
activation record
previous
activation record
15
By Value-Result
For passing parameters by value-result, the formal
parameter is just like a local variable in the activation
record of the called method. It is initialized using the
value of the corresponding actual parameter, before
the called method begins executing. Then, after the
called method finishes executing, the final value of the
formal parameter is assigned to the actual parameter.


7/7/2015
Also called copy-in/copy-out
Actual must have an lvalue
16
void plus(int a, by-value-result int b) {
b += a;
}
void f() {
int x = 3;
plus(4, x);
current
}
activation record
plus(4,x)
When plus
is starting
7/7/2015
f()
a: 4
x: 3
b: 3
return address
return address
previous
activation record
previous
activation record
17
void plus(int a, by-value-result int b) {
b += a;
}
void f() {
int x = 3;
plus(4, x);
current
}
activation record
plus(4,x)
When plus is
ready to return
7/7/2015
f()
a: 4
x: 3
b: 7
return address
return address
previous
activation record
previous
activation record
18
void plus(int a, by-value-result int b) {
b += a;
}
void f() {
int x = 3;
plus(4, x);
current
}
activation record
f()
When plus
has returned
7/7/2015
a: 4
x: 7
b: 7
return address
return address
previous
activation record
previous
activation record
19
Why call by Value-Result?
f():
int x = 3;
fork: {
check_d(4, x);
check_d(5, x);
}
f():
x:
3
check_d(int a,
int value-result b)
b = ....;
check_d1():
check_d1():
a:
4
a:
5
}
b:
3
b:
3
7/7/2015
8
7
20
By Reference (address)
For passing parameters by reference, the lvalue of the
actual parameter is computed before the called method
executes. Inside the called method, that lvalue is used
as the lvalue of the corresponding formal parameter.
In effect, the formal parameter is an alias for the
actual parameter—another name for the same memory
location.



7/7/2015
One of the earliest methods:
Fortran
Most efficient for large objects
Still frequently used
21
&
void plus(int a, by-reference int b) {
b += a;
}
void f() {
int x = 3;
plus(4, x);
current
}
activation record
Can this be 4?
When plus
is starting
7/7/2015
plus(4,x)
f()
a: 4
x: 3
b:
return address
return address
previous
activation record
previous
activation record
22
void plus(int a, by-reference int b) {
b += a;
}
void f() {
int x = 3;
plus(4, x);
}
current
activation record
plus(4,x)
When plus
has made the
assignment
7/7/2015
f()
a: 4
x: 7
b:
return address
return address
previous
activation record
previous
activation record
23
Previous example in C
void plus(int a, int & b) {
b += a;
}
This is call by reference
void f() {
int x = 3;
plus(4, x);
}
void plus(int a, int *b) {
*b += a;
}
This is call by value
void f() {
int x = 3;
plus(4, &x);
}
7/7/2015
24
Will array x be modified?
void F( int a[]) {
a[1]=a[1]+1;...
}
call by value
7/7/2015
int x[5];
F(x);
....
call by reference
?
25
Tricky
Will array x be modified?
void F(int * a) {
a = new int[10];...
}
void F(int a[]) {
a = new int[10];...
}
int x[5];
F(x);
....
int x[5];
F(x);
....
call by value
call by value
This is what java does!!
7/7/2015
26
Aliasing


When two expressions have the same
lvalue, they are aliases of each other
Obvious cases:
ConsCell x = new ConsCell(0,null);
ConsCell y = x;
7/7/2015
27
Aliases: expressions that have the same lvalue
Aliasing in call by reference
void sigsum(by-reference int n,
by-reference int ans) {
ans = 0;
int i = 1;
while (i <= n) ans += i++;
}
int f() {
int x,y;
x = 10;
sigsum(x,y);
return y;
}
7/7/2015
int g() {
int x;
x = 10;
sigsum(x,x);
return x;
}
28
Trouble caused by Alias
void sigsum(by-reference int x,
by-reference int bound) {
while (x <= bound) x++;
}
int a=10;
sigsum(a,a);
7/7/2015
29
By Macro Expansion
1. The body of the macro is evaluated in the caller’s
context.
2. Each actual parameter is evaluated on every use in
the body (in the caller’s context).


7/7/2015
Like C macros
Natural implementation: textual
substitution before compiling
30
Macro Expansions In C
source
file
pre-processor
source
file:
expanded
source
compiler
assemblylanguage
file
#define MIN(X,Y) ((X)<(Y)?(X):(Y))
....
....
a = MIN(b,c);
....
expanded
source:
7/7/2015
....
a = ((b)<(c)?(b):(c))
31
Preprocessing



7/7/2015
Replace each use of the macro with
a copy of the macro body, with
actuals substituted for formals
An old technique, used in
assemblers before the days of highlevel languages
It has some odd effects…
32
A little trouble
#define M(X,Y)
source
file:
expanded
source:
X = 2*Y
....
....
M(a,b+c);
....
....
a = 2*b+c;
7/7/2015
33
Repeated Evaluation
 Each actual parameter is re-evaluated upon
every use
#define MIN(X,Y) ((X)<(Y)?(X):(Y))
.....
a = MIN(f(b),f(c));
a = ((f(b))<(f(c))?(f(b)):(f(c)))
.....
a = MIN(b++,c++);
7/7/2015
a = ((b++)<(c++)?(b++):(c++))
34
Capture, used to be a big problem in logic
T  xy(x=y+c+d)
free variables
capture c
H  c T
H 
 cxy(x=y+c+d)
free variable
7/7/2015
35
Capture in actuals (Bad form)
Most PL’s macro expansions do that! Bad!!
g(a)   cxy(x=y+c+a)
free variable
h  g(c)
capture
h =  cxy(x=y+c+c)
7/7/2015
36
Solution to bad capture:
Conversion
T(c)  xy(x=y+c+d)
H  x T(x)
xxy(x=y+x+d)
Conversion: x  a
T(c)  ay(a=y+c+d)
incorrect
H   xay(a=y+x+d)
Most PL’s macro expansions don’t do that
7/7/2015
37
Capture in PL


Bad
Logic
In a program fragment, any
occurrence of a variable that is not
statically bound is free
When a fragment is moved to a
different context, its free variables can
become bound
This phenomenon is called capture:


7/7/2015
Free variables in the actuals can be
captured by definitions in the macro body
Also, free variables in the macro body can
be captured by definitions in the caller
38
Capture Example
#define intswap(X,Y) {int temp=X; X=Y; Y=temp;}
int main() {
int temp=1, b=2;
intswap(temp,b);
……
Source code
}
Expanded code
int main() {
int temp=1, b=2;
{int temp = temp ;
……
}
temp = b ;
b =temp;} ;
x is captured by temp
7/7/2015
39
By Name (a way to avoid previous bad capture)
Each actual parameter is evaluated in the caller’s context on
every use of the corresponding formal parameter.



7/7/2015
Like macro expansion without
capture
Algol 60 and others
Now unpopular
40
Implementing By-Name



7/7/2015
The actual parameter is treated like
a little anonymous function
Whenever the called method needs
the value of the formal (either
rvalue or lvalue) it calls the function
to get it
The function must be passed with
its nesting link, so it can be
evaluated in the caller’s context
41
Call by name Example
intswap(by-name int X, by-name int Y){
int temp=X; X=Y; Y=temp;}
temp()
int main() {
b()
int temp=1, b=2;
intswap(temp,b);
intswap(x, y)
……
}
temp = X;
X = Y;
Y = temp;
7/7/2015
Main()
Return Address
Return Address
Previous
Activation Record
Previous
Activation Record
local variable
:
temp: 1
local variable
:
temp:1 2
b:2 1
42
void f(by-name int a, by-name int b) {
b=5;
b=a;
current
}
activation record
int g() {
int i = 3;
f(i+1,i);
return i;
}
i = 5;
i = i+1;
7/7/2015
6
i+1
5i
5
a:
i: 3
b:
return address
return address
previous
activation record
previous
activation record
result: ?
43
Comparison



7/7/2015
Like macro expansion, by-name
parameters are re-evaluated every
time they are used
(Can be useful, but more often this
is merely wasteful)
Unlike macro expansion, there is no
possibility of capture.
44
By Need
Each actual parameter is evaluated in the caller’s
context, on the first use of the corresponding formal
parameter. The value of the actual parameter is then
cached, so that subsequent uses of the corresponding
formal parameter do not cause reevaluation.


7/7/2015
Used in lazy functional languages
(Haskell and other Languages)
Avoids wasteful re-computations of
by-name
45
void f(by-need int a, by-need int b) {
b=a;
b=a;
current
}
activation record
void g() {
int i = 3;
f(i+1,i);
return i;
}
/* a = i+1;
b = a;
b = a;
7/7/2015
i+1
i
*/
4
3
4
a:
i: 3
b:
return address
return address
previous
activation record
previous
activation record
result: ?
46
void f(by-name int a, by-name int b) {
b=a;
b=a;
current
}
i+1
activation record
45
void g() {
int i = 3;
f(i+1,i);
return i;
}
i = i+1;
i = i+1;
7/7/2015
5
4
3
i
4
a:
i: 3
b:
return address
return address
previous
activation record
previous
activation record
result: ?
5
47
Laziness: compute only when necessary
boolean andand(by-need boolean a,
by-need boolean b) {
if (a) return true;
else return b;
Compute b only
}
when necessary
void f() {
andand(sometest(),g());
}
boolean g() {
while (true) { }
return true;
}
7/7/2015
48