Uploaded by dzawa

Worksheet Argument Passing

advertisement
11/11/2020
Worksheet Argument Passing
Worksheet Argument Passing
Table of Contents
1. Questions and Completion
2. Finding Current Information
3. L-Value or Not?
4. Argument Passing
4.1. CBV in C - Int
4.2. CBV in C - Pointer
4.3. CBV in Java - Int
4.4. CBV in Java - Reference
4.5. Scala - Reference
4.6. C - Struct
5. Returning Two Items
5.1. Java - Immutable Pair Class
5.2. Java - Mutable Pair Class
5.3. C - Immutable Struct
5.4. C - Mutable Pair Struct
6. Scope and Recursive Values
7. Solutions
7.1. Solution: L-Value or Not?
7.2. Solution: CBV in C
7.3. Solution: CBV in Java
7.4. Solution: Returning Two Items - Java - Immutable Pair Class
7.5. Solution: Returning Two Items - Java - Mutable Pair Class
7.6. Solution: Returning Two Items - C - Immutable Pair Struct
7.7. Solution: Returning Two Items - C - Mutable Pair Struct
7.8. Solution: Scope and Recursive Values
1 Questions and Completion
To receive credit for completing the worksheet, you must complete the corresponding quiz (it is just a checkbox) on D2L when you have finished the
worksheet.
If you have questions as you go through this worksheet, please feel free to post them on the discussion forum.
2 Finding Current Information
The Concepts textbook is helpful in providing some information for topics this week. However, implementation details differ significantly between PLs,
so it is necessary to supplement textbook reading with experiments and more current information online (often blog posts of experiments by other
people). Unfortunately, book length treatments of implementation details are becoming rarer as their shelf-life decreases.
3 L-Value or Not?
In each of the following contexts, determine whether the given expression is an l-value or not. Your code should replace the ellipsis (...).
1. Is x++ an l-value in C? The context is:
void f (int x) {
}
...
2. Is arr[x++] an l-value in C? The context is:
void f (int x) {
int arr[] = { 5, 6, 7, 8, 9, 10, 11 };
}
...
3. Is f ().x an l-value in C? The context is:
struct S {
int x;
int y;
https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html
1/11
11/11/2020
Worksheet Argument Passing
};
struct S f () {
struct S s;
s.x = 5;
s.y = 6;
}
return s; // returns a copy of the "struct S", i.e., copies the two int members back
void g () {
}
...
4. Is t.x an l-value in C? The context is:
struct S {
int x;
int y;
};
struct S f () {
struct S s;
s.x = 5;
s.y = 6;
}
return s; // returns a copy of the "struct S", i.e., copies the two int members back
void g () {
struct S t = f ();
}
...
5. Is f ()->x an l-value in C? Recall that this means (*(f())).x, i.e., call f, dereference the pointer, then access the x member of the struct. The
context is:
#include <stdlib.h>
struct S {
int x;
int y;
};
struct S *f () {
struct S *p = (struct S *) malloc (sizeof (struct S));
p->x = 5;
// recall that p->x is just shorthand for (*p).x
p->y = 6;
}
return p; // returns a copy of the pointer, i.e., copies just a pointer back
void g () {
}
...
6. Is arr[x++] an l-value in Java? The context is:
class LValue6 {
static void f (int x) {
int[] arr = { 5, 6, 7, 8, 9, 10, 11 };
}
}
...
7. Is list.get (x++) an l-value in Java? The context is:
import java.util.ArrayList;
class LValue7 {
static void f (int x) {
ArrayList<Integer> list = new ArrayList<> ();
list.add (5);
https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html
2/11
11/11/2020
Worksheet Argument Passing
}
}
list.add (6);
list.add (7);
list.add (8);
...
8. Is list.get (x++).x an l-value in Java? The context is:
import java.util.ArrayList;
class C {
int x;
int y;
C (int x, int y) {
this.x = x;
this.y = y;
}
}
class LValue8 {
static void f (int x) {
ArrayList<C> list = new ArrayList<> ();
list.add (new C (5, 5));
list.add (new C (6, 6));
list.add (new C (7, 7));
list.add (new C (8, 8));
}
}
...
Solution: L-Value or Not?
4 Argument Passing
4.1 CBV in C - Int
Confirm that C uses call-by-value to pass int variables by writing a simple C program then running it.
4.2 CBV in C - Pointer
Confirm that C uses call-by-value to pass pointer variables by writing a simple C program then running it.
Solution: CBV in C?
4.3 CBV in Java - Int
Confirm that Java uses call-by-value to pass int variables by writing a simple Java program then running it.
4.4 CBV in Java - Reference
Confirm that Java uses call-by-value to pass reference variables (meaning references to instances on the heap) by writing a simple Java program then
running it.
Solution: CBV in Java?
4.5 Scala - Reference
When the following Scala program is executed it prints C(10). Can we conclude that Scala uses call-by-reference?
case class C (var x:Int)
object Test {
def f (o:C) = {
o.x = 10
}
def main (args:Array[String]) = {
val c = C (5)
https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html
3/11
11/11/2020
}
}
Worksheet Argument Passing
f (c)
println (c)
4.6 C - Struct
Examine the following C program. A struct S contains two int members (like fields) and an array of int (length is ARR_SIZE or 16).
#include <stdio.h>
#include <stdlib.h>
#define ARR_SIZE 16
struct S {
int x;
int y;
int arr[ARR_SIZE];
};
void print_S (struct S *p) {
printf ("S {\n x = %d,\n y = %d,\n
for (int i = 0; i < ARR_SIZE; i++) {
printf ("%02X, ", p->arr[i]);
}
printf ("],\n}\n");
}
arr = [ ", p->x, p->y);
void f (struct S s) {
printf ("s in f #1\n");
print_S (&s);
s.x = s.x + 1;
/* increment s.x
(first way to write it) */
s.y += 1;
/* increment s.y
(second way to write it) */
for (int i = 0; i < ARR_SIZE; i++) {
s.arr[i]++;
/* increment s.arr[i] (third way to write it) */
}
}
printf ("s in f #2\n");
print_S (&s);
int main (void) {
struct S t;
t.x = 5;
t.y = 6;
}
for (int i = 0; i < ARR_SIZE; i++) {
t.arr[i] = i;
}
//printf ("sizeof(struct S)=%lu\n", sizeof(struct S));
printf ("t in main #1\n");
print_S (&t);
f (t);
printf ("t in main #2\n");
print_S (&t);
1. How big is a struct S? (You can check your answer afterwards by adding a line to print sizeof(struct S).)
2. In contrast how big is each field in an instance of this Java class?
class S {
int x;
int y;
int[] arr;
}
3. The main function allocates a variable t of type struct S in its activation on the call-stack. We often say that t is stack-allocated. The function f is
called with t as an argument. The function f prints the contents of its argument, updates its argument, then prints the contents again. Finally main
prints the contents of t again. Try to work out will be printed, given the statement "C copies structures when passed as arguments". Confirm your
answer by compiling and running the C program.
4. Rewrite the C program so that f receives a pointer to a struct S, and does its updates via that pointer. Try to work out how that will affect the
output. Recompile and run your program to confirm your answer.
https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html
4/11
11/11/2020
Worksheet Argument Passing
5 Returning Two Items
It is often necessary to return two or more items from a function or method.
In Scala, tuple types can be used to return two items. For example, fibaux below performs an efficient calculation of the n and n+1 elements of the
Fibonacci sequence. By returning a pair of two consecutive numbers from the Fibonacci sequence it avoids the unnecessary recomputation in the naive
definition of the Fibonacci function.
def fibaux (n:BigInt) : (BigInt, BigInt) = {
if (n <= 0) {
(0, 1)
} else if (n == 1) {
(1, 1)
} else {
val (a, b) = fibaux (n - 1)
(b, a + b)
}
}
def fib (n:BigInt) : BigInt = fibaux (n)._1
For example:
scala> (0 to 70).toList.map (n => BigInt (n)).map (fib)
res0: List[BigInt] = List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 2
Now consider how to return two or more items in other programming languages.
5.1 Java - Immutable Pair Class
The following Java program defines an immutable Pair class (with type parameters X and Y). Complete the definition of fibaux in the following Java
program, which uses the immutable Pair class. You may need to refer to the Java documentation for use of Java's BigInteger class.
import java.math.BigInteger;
class Pair<X,Y> {
final X x;
final Y y;
Pair (X x, Y y) {
this.x = x;
this.y = y;
}
}
public class Fib1 {
static Pair<BigInteger,BigInteger> fibaux (BigInteger n) {
}
...
static BigInteger fib (BigInteger n) {
return fibaux (n).x;
}
}
public static void main (String[] args) {
for (int i = 0; i < 71; i++) {
System.out.println (fib (BigInteger.valueOf (i)));
}
}
Solution: Returning Two Items - Java - Immutable Pair Class
5.2 Java - Mutable Pair Class
If the final modifier is removed from the fields of Pair, the caller to fibaux can pass in (a reference to) a Pair instance, and the fields of that instance
can be updated with the results. Complete the definition of fibaux in the following Java program.
https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html
5/11
11/11/2020
Worksheet Argument Passing
import java.math.BigInteger;
class Pair<X,Y> {
X x;
Y y;
Pair (X x, Y y) {
this.x = x;
this.y = y;
}
}
public class Fib2 {
static void fibaux (BigInteger n, Pair<BigInteger,BigInteger> result) {
}
...
static BigInteger fib (BigInteger n) {
Pair<BigInteger, BigInteger> p = new Pair<> (BigInteger.ZERO, BigInteger.ZERO);
fibaux (n, p);
return p.x;
}
}
public static void main (String[] args) {
for (int i = 0; i < 71; i++) {
System.out.println (fib (BigInteger.valueOf (i)));
}
}
Solution: Returning Two Items - Java - Mutable Pair Class
5.3 C - Immutable Struct
The following C program defines an immutable pair struct. We use long for simplicity instead of an arbitrary precision data type for integers. Complete
the definition of fibaux in the following C program, which uses the immutable pair struct.
#include <stdio.h>
#include <stdlib.h>
struct pair {
const long x;
const long y;
};
struct pair fibaux (long n) {
}
...
long fib (long n) {
return fibaux (n).x;
}
int main (void) {
for (int i = 0; i < 71; i++) {
printf ("%ld\n", fib (i));
}
}
Solution: Returning Two Items - C - Immutable Pair Struct
5.4 C - Mutable Pair Struct
Explain why we cannot remove the const modifier from the members of struct pair and then rewrite fibaux with the following signature (contrast
with the Java mutable Pair class above).
struct pair {
long x;
long y;
};
https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html
6/11
11/11/2020
Worksheet Argument Passing
void fibaux (long n, struct pair result) {
}
...
Explain how to change the signature of fibaux so that an argument for the result can be passed to fibaux.
Solution: Returning Two Items - C - Mutable Pair Struct
6 Scope and Recursive Values
1. Write a Scala expression alternates of type Stream[Boolean] that alternates between true and false (starting with true).
2. Try the following expressions in the Scala REPL (after your definition of alternates).
"the rain in spain".toList
"the rain in spain".toList.zip (alternates)
"the rain in Spain".toList.zip (alternates).filter ((p:(Char,Boolean)) => p match { case (c:Char,b:Boolean) => b })
/* shorthand for the previous version */
"the rain in Spain".toList.zip (alternates).filter { case (c:Char,b:Boolean) => b }
"the rain in Spain".toList.zip (alternates).filter { case (c:Char,b:Boolean) => b }
val evens = "the rain in Spain".toList.zip (alternates).filter { case (c:Char,b:Boolean) => b }.map (p => p._1)
val odds = "the rain in Spain".toList.zip (alternates).filter { case (c:Char,b:Boolean) => !b }.map (p => p._1)
evens.zip (odds)
7 Solutions
7.1 Solution: L-Value or Not?
1. No, temporary value from ++
2. Yes, array
3. No, temporary value from f()
4. Yes, struct
5. Yes, pointer is temporary, but field is not
6. Yes, array
7. No, temporary Integer
8. Yes, all object access via pointers/references in Java
7.2 Solution: CBV in C
#include <stdio.h>
void swapInt(int x, int y) {
int oldX = x;
int oldY = y;
x = oldY;
y = oldX;
}
void swapPointer(int *x, int *y) {
int* oldX = x;
int* oldY = y;
x = oldY;
y = oldX;
}
int main() {
{
int a = 0;
int b = 1;
printf ("a = %d, b = %d\n", a, b);
swapInt (a, b);
printf ("a = %d, b = %d\n", a, b);
}
{
int a = 0; int *p = &a;
int b = 1; int *q = &b;
printf ("*p = %d, *q = %d\n", *p, *q);
https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html
7/11
11/11/2020
}
}
Worksheet Argument Passing
swapPointer (p, q);
printf ("*p = %d, *q = %d\n", *p, *q);
7.3 Solution: CBV in Java
class CBV {
private static void swapInt(int x, int y) {
int oldX = x;
int oldY = y;
x = oldY;
y = oldX;
}
private static void swapRef(Integer x, Integer y) {
Integer oldX = x;
Integer oldY = y;
x = oldY;
y = oldX;
}
}
public static void main(String args[]) {
{
int a = 0;
int b = 1;
System.out.format ("a = %d, b = %d\n",
swapInt (a, b);
System.out.format ("a = %d, b = %d\n",
}
{
Integer a = 0;
Integer b = 1;
System.out.format ("a = %d, b = %d\n",
swapRef (a, b);
System.out.format ("a = %d, b = %d\n",
}
}
a, b);
a, b);
a, b);
a, b);
7.4 Solution: Returning Two Items - Java - Immutable Pair Class
import java.math.BigInteger;
class Pair<X,Y> {
final X x;
final Y y;
Pair (X x, Y y) {
this.x = x;
this.y = y;
}
}
public class Fib1 {
static Pair<BigInteger,BigInteger> fibaux (BigInteger n) {
if (n.compareTo (BigInteger.ZERO) <= 0) {
return new Pair<> (BigInteger.ZERO, BigInteger.ONE);
} else if (n.equals (BigInteger.ONE)) {
return new Pair<> (BigInteger.ONE, BigInteger.ONE);
} else {
Pair<BigInteger, BigInteger> p = fibaux (n.subtract (BigInteger.ONE));
return new Pair<> (p.y, p.x.add (p.y));
}
}
static BigInteger fib (BigInteger n) {
return fibaux (n).x;
}
public static void main (String[] args) {
for (int i = 0; i < 71; i++) {
System.out.println (fib (BigInteger.valueOf (i)));
https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html
8/11
11/11/2020
}
}
Worksheet Argument Passing
}
$ javac Fib1.java
$ java Fib1
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
28657
46368
75025
121393
196418
317811
514229
832040
1346269
2178309
3524578
5702887
9227465
14930352
24157817
39088169
63245986
102334155
165580141
267914296
433494437
701408733
1134903170
1836311903
2971215073
4807526976
7778742049
12586269025
20365011074
32951280099
53316291173
86267571272
139583862445
225851433717
365435296162
591286729879
956722026041
1548008755920
2504730781961
4052739537881
6557470319842
10610209857723
17167680177565
27777890035288
44945570212853
72723460248141
117669030460994
190392490709135
7.5 Solution: Returning Two Items - Java - Mutable Pair Class
https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html
9/11
11/11/2020
Worksheet Argument Passing
import java.math.BigInteger;
class Pair<X,Y> {
X x;
Y y;
Pair (X x, Y y) {
this.x = x;
this.y = y;
}
}
public class Fib2 {
static void fibaux (BigInteger n, Pair<BigInteger,BigInteger> result) {
if (n.compareTo (BigInteger.ZERO) <= 0) {
result.x = BigInteger.ZERO;
result.y = BigInteger.ONE;
} else if (n.equals (BigInteger.ONE)) {
result.x = BigInteger.ONE;
result.y = BigInteger.ONE;
} else {
fibaux (n.subtract (BigInteger.ONE), result);
BigInteger x = result.x;
BigInteger y = result.y;
}
}
result.x = y;
result.y = x.add (y);
static BigInteger fib (BigInteger n) {
Pair<BigInteger, BigInteger> p = new Pair<> (BigInteger.ZERO, BigInteger.ZERO);
fibaux (n, p);
return p.x;
}
}
public static void main (String[] args) {
for (int i = 0; i < 71; i++) {
System.out.println (fib (BigInteger.valueOf (i)));
}
}
7.6 Solution: Returning Two Items - C - Immutable Pair Struct
#include <stdio.h>
#include <stdlib.h>
struct pair {
const long x;
const long y;
};
struct pair fibaux (long n) {
if (n <= 0) {
return (struct pair) { 0, 1 };
} else if (n == 1) {
return (struct pair) { 1, 1 };
} else {
struct pair p = fibaux (n - 1);
return (struct pair) { p.y, p.x + p.y };
}
}
long fib (long n) {
return fibaux (n).x;
}
int main (void) {
for (int i = 0; i < 71; i++) {
printf ("%ld\n", fib (i));
}
}
https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html
10/11
11/11/2020
Worksheet Argument Passing
7.7 Solution: Returning Two Items - C - Mutable Pair Struct
It would not work because fibaux would receive a copy of the struct pair from the caller, so modifications to result would not be seen by the caller.
To modify the program, we pass a pointer to a struct pair instead, and fibaux fills in its value.
#include <stdio.h>
#include <stdlib.h>
struct pair {
long x;
long y;
};
void fibaux (long n, struct pair *presult) {
if (n <= 0) {
presult->x = 0;
presult->y = 1;
} else if (n == 1) {
presult->x = 1;
presult->y = 1;
} else {
fibaux (n - 1, presult);
long x = presult->x;
long y = presult->y;
}
}
presult->x = y;
presult->y = x + y;
long fib (long n) {
struct pair result; // not initialized here, will be initialized by fibaux
fibaux (n, &result);
return result.x;
}
int main (void) {
for (int i = 0; i < 71; i++) {
printf ("%ld\n", fib (i));
}
}
7.8 Solution: Scope and Recursive Values
val alternates:Stream[Boolean] = true #:: false #:: alternates
Author: James Riely
Created: 2020-10-27 Tue 17:12
Emacs 25.3.50.1 (Org mode 8.2.10)
Validate
https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html
11/11
Download