12.3 Survey of Parameter-Passing Mechanisms

We start by surveying parameter-passing mechanisms in a variety of languages prior to discussing implementation strategies for these mechanisms.

12.3.1 Pass-by-Value

Pass-by-value is a parameter-passing mechanism in which copies of the arguments are passed to the function. For this reason, pass-by-value is sometimes referred to as pass-by-copy. Consider the classical swap function in C:

A set of 21 code lines in C with the swap function.
Description
A set of 21 code lines in C with the swap function.

C only passes arguments by value (i.e., by copy). Figure 12.2 shows the run-time stack of this swap function with signature void swap(int a, int b):

An illustration of a matrix for passing arguments by value in C.

Figure 12.2 Passing arguments by value in C. Therun-timestack grows upward. (Key: □ = memory cell; … = activation-record boundary.)

Description
  1. (top left) Before swap is called.

  2. (top right) After swap is called. Notice that copies of x and y are passed in.

  3. (bottom left) While swap executes. Notice that the swap takes place within the activation record of the swap function, not main.

  4. (bottom right) After swap returns.

As can be seen, the function does not swap the two integers.

Java also only passes arguments by value. Consider the following swap method in Java, which accepts integer primitives as arguments:

A set of 21 code lines in Java with the function swap.
Description

The output of this program is

A set of five lines of output of a Java program.
Description

The status of the run-time stack in Figure 12.2 applies to this Java swap method with signature void swap(int a, int b) as well. Since all parameters, including primitives, are passed by value in Java, this swap method does not swap the two integers. Consider the following version of the swap program in Java, where the arguments to the swap method are references to objects instead of primitives:

A set of six code lines in Java with the function swap.
Description
Continuation of the code in Java with the function swap, consisting of 15 lines.
Description

The output of this program is

A set of five lines of output of a Java program.
Description

Figure 12.3 illustrates the run-time stack during the execution of this Java swap method with signature void swap(Integer a, Integer b):

An illustration of a matrix for the passing of references by value in Java.

Figure 12.3 Passing of references (to objects) by value in Java. The run-time stack grows upward. (Key: □ = memory cell; ο =object; ⋄→ = reference; … = activation-boundary.)

Description
  1. (top left) Before swap is called. Notice the denoted values of x and y are references to objects.

  2. (top right) After swap is called. Notice that copies of the references x and y are passed in.

  3. (bottom left) While swap executes. Notice that the references are swapped rather than the objects to which they point. As before, the swap takes place within the activation record of the swap method, not main.

  4. (bottom right) After swap returns.

As can be seen, this swap method does not swap its Integer object-reference arguments. The references to the objects in main are not swapped because “Java manipulates objects ’by reference,’ but it passes object references to methods ’by value’” (Flanagan 2005). Consequently, a swap method intended to swap primitives or references to objects cannot be defined in Java.

Scheme also only supports passing arguments by value. Thus, as in Java, references in Scheme are passed by value. However, unlike in Java, all denoted values are references to expressed values in Scheme. Consider the following Scheme program:

A set of three code lines in a Scheme program with the definition of swap.
Description
Continuation of the code in a Scheme program with the definition of swap, consisting of 23 lines.
Description

The output of this program is

A set of three lines of output of a Scheme program.
Description

Figure 12.4 depicts the run-time stack as this Scheme program executes:

An illustration of a matrix for the passing of arguments in Scheme.

Figure 12.4 Passing arguments by value in Scheme. The run-time stack grows upward. (Key: □ = memory cell; ⋄→ = reference; … = activation-record boundary.)

Description
  1. (top left) Before swap is called. Notice the denoted values of x and y are references to expressed values.

  2. (top right) After swap is called. Notice that copies of the references x and y are passed in.

  3. (bottom left) While swap executes. Notice that it is the references that are swapped. As before, the swap takes place within the activation record of the swap function, not the outermost let expression.

  4. (bottom right) After swap returns.

As can be seen, this swap function does not swap its reference arguments.

Passing a reference by copy has been referred to as pass-by-sharing, especially in languages where all denoted values are references (e.g., Scheme, and Java except for primitives), though use of that term is not common.

Notice also the primary difference between denoted values in C and Scheme in Figures 12.2 and 12.4, respectively. In Scheme, all denoted values are references to expressed values; in C, denoted values are the same as expressed values. We need to explore the pass-by-reference parameter-passing mechanism to define a swap function that successfully swaps its arguments in the calling function (i.e., persistently).

12.3.2 Pass-by-Reference

In the pass-by-reference parameter-passing mechanism, the called function is passed a direct reference to the argument. As a result, changes made to the corresponding parameter in the called function affect the value of the argument in the calling function. Consider the classical swap function in C++:

A set of 12 code lines in C plus plus with the function swap.
Description
Continuation of the code in C plus plus with the function swap, consisting of 13 lines.
Description

C++ supports both the pass-by-value and pass-by-reference parameter-passing mechanisms. Pass-by-value is the default mechanism in C++. To use pass-byreference, append an & (ampersand) to the end of the data type of any parameter in the signature of the called function that you desire to be passed by reference. Figure 12.5 illustrates the run-time stack during the execution of this C++ swap function with signature void swap(int& a, int& b):

An illustration of a matrix for the pass-by-reference parameter-passing mechanism in C plus plus.

Figure 12.5 The pass-by-reference parameter-passing mechanism in C++. The runtime stack grows upward. (Key: □ = memory cell; ⋄→ = reference; … = activation-record boundary.)

Description
  1. (top left) Before swap is called. Notice the denoted values of x and y are int and not references to integers.

  2. (top right) After swap is called. Notice that references to x and y are passed in.

  3. (bottom left) While swap executes. Notice that changes to the parameters a and b are reflected in the arguments x and y in main. Thus, unlike with pass-by-value, the swap here takes place within the activation record of the main function, and not swap.

  4. (bottom right) After swap returns.

As can be seen, this swap function does swap its integer arguments.

As discussed previously, C supports only pass-by-value. However, we can simulate pass-by-reference in C by passing the memory address of a variable by value. Consider the following C program:

A set of 14 code lines in C with the simulated-pass-by reference analog.
Description
Continuation of the code in C with the simulated-pass-by-reference analog, consisting of 23 lines.
Description

This program is the simulated-pass-by-reference analog of the pass-by-value swap program in C. The & operator returns the memory address of its variable argument. (e.g., &x and &y on lines 21, 24, and 27). The * operator (e.g., *a and *b on lines 6–8) is the pointer dereferencing operator in C, which returns the value to which its variable argument points rather than the denoted value of its variable argument. In C, * is an overloaded operator. When it appears after the name of a data type, it denotes a pointer type. Thus, int is the integer data type and int* is the integer pointer data type. A variable of type int* is an 8-byte memory cell that stores a hexadecimal address that points to a 4-byte integer. The signature of this swap function is void swap(int* a, int* b). Unlike the prior signature [i.e., void swap(int a, int b)], this function does not accept two integers as arguments. Instead, it accepts two addresses to int as arguments (i.e., two variables, each of type int*). Figure 12.6 shows the status of the run-time stack of this swap function with signature void swap(int* a, int* b):

An illustration of a matrix for passing memory-address arguments by value in C.

Figure 12.6 Passing memory-address arguments by value in C. The run-time stack grows upward. (Key: □ = memory cell; … = activation-record boundary.)

Description
  1. (top left) Before swap is called.

  2. (top right) After swap is called. Notice that copies of the addresses of the integers x and y are passed in (i.e., the address of x and y are passed in; see line 24, where &x = 16ec and &y = 16e8).

  3. (bottom left) While swap executes. By dereferencing the pointers a and b (see *a and *b on lines 6–8), the swap function is swapping the value to which the memory addresses denoted by a and b point, rather than swapping the actual memory addresses. Here, the swap takes place within the activation record of the main function, not swap.

  4. (bottom right) After swap returns.

As can be seen, the function does swap the two integers. But notice that the addresses are still passed by value. (Recall that passing references by value or, in other words, simulated pass-by-reference, has been called pass-by-sharing.) In general, for a C function to modify (i.e., mutate) a variable that is not local to the function, but is also not a global variable, the function must receive a copy of the memory address of the variable it intends to modify rather than its value.

Pass-by-value and pass-by-reference are the two most widely supported parameter-passing mechanisms in programming languages. However, a variety of other mechanisms are supported, especially the pass-by-name and pass-byneed approaches, which are commonly referred to as lazy evaluation (Section 12.5). We complete this section by briefly discussing pass-by-result and pass-by-valueresult.

12.3.3 Pass-by-Result

In the pass-by-value mechanism, copies of the values of the arguments are passed to the called function by copy, but nothing is passed back to the caller. The pass-by-result parameter-passing mechanism is the reverse of this approach: No data is passed in to the called function, but copies of the values of the parameters in the called function are passed back to the caller. Consider the following C program:

A set of two code lines in a C program with pass-by-result parameter-passing mechanism.
Description
Continuation of the code in a C program with pass-by-result parameter-passing mechanism, consisting of 21 lines.
Description

The output of this program is

A set of four lines of output of a C program with pass-by-result parameter-passing mechanism.
Description

Note that C syntax is used here only for purposes of illustration; it is not intended to convey that C uses the pass-by-result parameter-passing mechanism. Figure 12.7 presents the run-time stack of this function with signature void f(int a, int b):

An illustration of a matrix for passing arguments by result.

Figure 12.7 Passing arguments by result. The run-time stack grows upward. (Key: □ = memory cell; … = activation-record boundary.)

Description
  1. (top left) Before f is called.

  2. (top right) After f is called. Notice that copies of x and y are not passed in.

  3. (bottom left) While f executes. Notice that the assignments take place within the activation record of the f function, not main.

  4. (bottom right) After f returns.

As shown in the output, the printf statement on line 3 is unable to print the values for a and b because no values are passed into f. The values of x and y in main after f returns are the final values of a and b in f.

12.3.4 Pass-by-Value-Result

Pass-by-value-result (sometimes referred to as pass-by-copy-restore) is a combination of the pass-by-value (on the front end of the call) and pass-by-result (on the back end of the call) parameter-passing mechanisms. In the pass-by-value-result mechanism, arguments are passed into the called function in the same manner as with the pass-by-value approach (i.e., by copy). However, the values of the corresponding parameters within the called function are passed back to the caller in the same manner as with the pass-by-result mechanism (i.e., by copy). Consider the following C program:

A set of 17 code lines in a C program with pass-by-value-result parameter-passing mechanism.
Description

The output of this program is

A set of four lines of output of a C program with pass-by-value-result parameter-passing mechanism.
Description

Again, C syntax is used here only for purposes of illustration; it is not intended to convey that C uses the pass-by-value-result mechanism. Figure 12.8 presents the run-time stack of this function with signature void f(int a, int b):

An illustration of a matrix for passing arguments by result.

Figure 12.8 Passing arguments by value-result. The run-time stack grows upward. (Key: □ = memory cell; … = activation-record boundary.)

Description
  1. (top left) Before f is called.

  2. (top right) After f is called. Notice that copies of x and y are passed in.

  3. (bottom left) While f executes. Notice that the additions and assignments take place within the activation record of the f function, not main.

  4. (bottom right) After f returns. Notice that copies of the values of the parameters a and b from the called function f are copied back to the calling function main.

12.3.5 Summary

The following abbreviations identify the direction in which data flows between the calling and called functions in parameter-passing mechanisms:

  • IN = data flows from the calling to the called function.

  • OUT = data flows from the called function back to the calling function.

  • IN-OUT = data flows both from the calling to the called function and from the called function back to the calling function.

The following is a classification using these mnemonics to help think about the parameter-passing mechanisms discussed in this section.

  • pass-by-value: IN

  • pass-by-result: OUT

  • pass-by-reference: IN-OUT

  • pass-by-value-result: IN at the front; OUT at the back

Although they may appear to be the same, note that

pass-by-reference (IN-OUT) ≠ pass-by-value-result (IN-OUT)

This inequality is explored in Programming Exercise 12.3.13.

The pass-by-value parameter-passing mechanism works the same way in all of the languages used to illustrate it here. The factor on which a successful swap depends is the sets of expressed and denoted values in each language. These sets do vary in C, C++, Java, and Scheme. Table 12.2 summarizes this and other factors in the languages discussed in this section in relation to parameter-passing. Figure 12.9 presents this tabular summary in a graphical fashion.

An illustration of the different parameter-passing concepts in different programming languages.

Figure 12.9 Summary of parameter-passing concepts in Java, Scheme, C, and C++. (Key: arrow from concept to language indicates source concept is supported in target language.)

Description

Table 12.2 Relationship Between Denoted Values, Dereferencing, and Parameter-Passing Mechanisms in Programming Languages Discussed in This Section

A table of denoted value, dereferencing, and parameter-passing mechanism for different languages.
Description

Conceptual Exercises for Section 12.3

Exercise 12.3.1 What are some of the disadvantages of the pass-by-value parameter-passing mechanism? Explain.

Exercise 12.3.2 Indicate which parameter-passing mechanisms the following programming languages support: Swift, Smalltalk, C#, Ruby, Python, and Perl.

Exercise 12.3.3 Which parameter-passing mechanism does ML use? Explain with reasons and defend your answer with code.

Exercise 12.3.4 Consider the following C program:

A set of 14 code lines in a C program.
Description

Give the output that the printf statement on line 9 produces if the arguments to the function f on line 8 are passed using the following parameter-passing mechanisms:

(a) pass-by-value

(b) pass-by-reference

(c) pass-by-result

(d) pass-by-value-result

Exercise 12.3.5 As illustrated in this section, we cannot write a swap method in Java because all variables in Java—both primitives and references to objects—are passed by value. Given this approach in Java, what could a programmer do to swap two integers in Java?

Exercise 12.3.6 Consider the following Java program:

A set of 23 code lines in a Java program.
Description

The output of this program is

A set of five lines of output in a Java program.
Description

Given that denoted values in Java are references for all identifiers declared as objects, such as i on line 13, explain why the i on line 21 in the main method does not reflect the incremented value of i (i.e., the value 6) after the call to the method increment on line 18.

Exercise 12.3.7 Consider the following C program:

A set of two lines of code in a C program.
Description
Continuation of the code in a C program consisting of 13 lines.
Description

Passing the arguments to the function f on line 12 using which of the parameter-passing mechanisms discussed in this section produces the following output:

A set of two lines of output for a C program.
Description

Defend your answer. There may be more than one answer.

Exercise 12.3.8 How can a called function, which is evaluated using the pass-byresult parameter-passing mechanism, reference a parameter whose corresponding argument is a literal or an expression [e.g., f(1,a+b);]?

Exercise 12.3.9 Can parameter collision [e.g., f(x,x);] occur in a function evaluated using the pass-by-value-result parameter-passing mechanism? Describe the problems that may occur.

Exercise 12.3.10 In the pass-by-result parameter-passing mechanism, when should the address of each parameter be evaluated?

Programming Exercises for Section 12.3

Exercise 12.3.11 Replicate in Python the pass-by-value swap function and program in C.

Exercise 12.3.12 Define a function in C, Python, or Scheme, and present an invocation of it, that produces different results when its arguments are passed by result and by value-result. Explain in comments in the program how one of the mechanisms produces different results than the other.

Exercise 12.3.13 Define a Python function, and present an invocation of it, that produces different results when its arguments are passed by value-result than when passed by reference. Explain in comments in the program how one of the mechanisms produces different results than the other. Keep the function to five lines of code or less.

Exercise 12.3.14 Write a swap method in Java that successfully swaps its arguments in the calling function. Hint: The arguments being swapped cannot be of type int or Integer, but rather must be references to objects whose data members of type int are the values being swapped.

Exercise 12.3.15 Is it possible to simulate pass-by-reference in Scheme? If so, write a Scheme function that demonstrates this simulation. Hint: Explore the concept of boxing in Scheme. Can you rewrite your function without boxing yet still simulate pass-by-reference? Explain. Provide your answer as a comment in your program.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.94.209