CS441 Midterm- 2
Name:
1. Answer the following questions concerning programming languages:
a. Why do you suppose that variable-length argument lists are so seldom supported by high-level programming languages?
The variables-length arguments are against to strong coupling and also make the optimization difficult.
b. What purpose(s) do types serve in a programming language? What does it mean for a language to be strongly typed? Statically typed? What prevents, say C or C++, from being strongly typed? Name two important programming languages that are strongly but dynamically typed.
Types keep track of a variable and how is it modified. When no application of an operator to arguments can lead to a run-time type error, language is strongly typed.If type rules are enforced strongly (that is, generally allowing only those automatic type conversions which do not lose information), the process is called strongly typed, if not, weakly typed. With statically-typed languages, there usually are pre-defined types for individual pieces of data (such as numbers within a certain range, strings of letters, etc.), and programmatically named values (variables) can have only one fixed type, and allow only certain operations: numbers cannot change into names and vice versa.
C, C++ support void pointers which should be changed to a type( typecaseted) before using it – which is violation on strongly typed. The explicit type cast allow coversions of types .
The programming languages which are strongly but dynamically typed are: Python and Perl.
c. In what ways may an enumeration type be preferable to a collection of named constants? In what ways may a subrange type be preferable to its base type? In what ways may a string be preferable to an array of characters?
When the named constants are really in order like days in a week or they have any relation to previous type and could be collected in a logic sequence, then enumeration is the best way representing such a collection of named constants.
Using subrange range checking is done in compile time rather than runtime.
If the operations to performed on strings instead on the chars of a string ( like strcat and changing the case of a string) then strings are preferred.
d. Explain the difference between type conversion, type coercion, and nonconverting type casts.
If the type of a variable is converted to another type (like narrowing and broadening) is called type conversion. Type coercion is for implicit operand type conversions. The non-converting type casts is when change of type without altering the underlying bits.
e. What is the difference between a pointer and an address? What are dangling references? How are they created, and why are they a problem? Discuss the comparative advantages of tombstones and locks and keys as a means of solving the problem.
Pointer holds the address of another variable. A pointer has address too. If a pointer points to an address, which is no longer valid, it is called a dangling reference.
f. What’s the difference between an activation record and an activation record instance?
An activation record is the data used by the subroutine while it is active that is not the subroutine’s code. An activation record instance is the data for a particular call to a subroutine
g. What are the two steps in locating a nonlocal variable in a static-scoped language with stack-dynamic local variables and nested subprograms?
o Find the correct activation record instance
o Determine the correct offset within that activation record instance
h. What’s the two potential problems with the static chain method?
1. A nonlocal reference is slow if the number of scopes between the reference and the declaration of the referenced variable is large
2. Time-critical code is difficult, because the costs of nonlocal references are not equal, and can change with code upgrades and fixes
i. What are the differences between the deep access and shallow access methods of implementing dynamic scoping?
Deep Access - nonlocal references are found by searching the activation record instances on the dynamic chain. Length of chain cannot be statically determined Every activation record instance must have variable names
In case of shallow access names and values are stored in a global table. Using this method, space is allocated for every variable name that is in the program(one space for variable temp though there might be several declarations of temp in the different methods). When a sub-routine is called it saves the current value of the variable and replaces it with the value in its current scope and restores the value of the variable while exiting.
2. consider the following C program:
int fun (int *i) {
*I += 5;
return 4;
}
void main () {
int x = 3;
x = x + fun(&x);
}
What is the value of x after the assignment statement in main?
a. If operands are evaluated left to right
b. If operands are evaluated right to left
a. x = 3 + 4 = 7
b. x = 8 + 4 = 12
3. Given the following Java-like code, what is the output of the program when each of the following scoping rules is applied? Explain your answers.
a. Static scope
b. Dynamic scope
public class A {
int x = 0;
void fa() {
int x = 1;
fb();
}
void fb() {
println("x = " + x)
}
public static void main(String[] args) {
new A().fa();
}
}
Suggested Solution
· Static Scope: The output is 0, since the variable x is declared as an instant variable of class A which is initialized to 0.
· Dynamic Scope: The output is 1, since the local variable x of method fa() is closer to the method fb() on the system stack when the prinln() statement is executed at runtime
4. Consider the following skeletal C program.
void fun1(void) {
int b, c, d;
// call another function
}
void fun2(void) {
int c, d, e;
// call another function
}
void fun3(void) {
int d, e, f;
// call another function
}
void main () {
int a, b, c;
// call another function
}
Given the following calling sequences and assuming that dynamic scoping is used, what variables are visible during execution of the last function called? Include with each visible variable the name of the function in which it was defined.
a. main calls fun2; fun2 calls fun3; fun3 calls fun1.
(b, c, d: fun1; e, f: fun3; a: main)
b. main calls fun3; fun3 calls fun1.
(b, c, d: fun1; e, f: fun3; a: main)
c. main calls fun1; fun1 calls fun3; fun3 calls fun2.
(c, d, e: fun2; f: fun3; b: fun1; a: main)
d. main calls fun3; fun3 calls fun2; fun2 calls fun1.
(b, c, d: fun1: e: fun2; f: fun3; a: main)
5. Pointer and reference type
(a) For a language with which you are familiar that provides a pointer type for programmer-constructed data objects and operations such as new and delete (or similar), which allocate and free storage for objects, write a code sample that generates garbage (i.e., useless objects that keep occupying memory space). Then, write a code sample that generates a dangling reference.
Suggested Solution:
(b) In your selected language, suggest programming techniques that could diminish the risk of generating garbage and dangling references. What language constructs in your selected language can be used to support your techniques (if any)?
Suggested Solution
C# is one such language which does automatic garbage collection. It is based on a usage approach that the unreferenced space and not usable space are freed up.
Further reading: http://msdn.microsoft.com/library/default.asp?url=/library/enus/
dndotnet/html/dotnetGCbasics.asp
6. Write (in a language of your choice or an appropriate pseudo-language) samples of procedures or functions that will have different effects, depending on whether arguments are passed by value, by reference, by value/result, or by name.
Let’s take examples of two swap functions
Void swap1(int x,int y)
{
int temp = x;
y = temp;
x= y;
}
Void swap2(int * x,int * y)
{
int temp = *x;
*y = temp;
*x= *y;
}
int main()
{
int x = 5,y=4;
swap1(x,y);
printf(“%d %d”,x,y); // prints 5 4 since this is pass by value
swap2(&x,&y);
printf(“%d %d”,x,y);
// prints 4 5 since this is pass by reference. The values in this case
// are stored in the address locations as indicated by &x and &y
}
7. Consider the following program written in C syntax:
void main () {
int value = 2, list[5] = {1, 3, 5, 7, 9};
swap (value, list[0]);
swap (list[0], list[1]);
swap (value, list[value]);
}
void swap (int a, int b) {
int temp;
temp = a;
a = b;
b = temp;
}
for each of the following parameter-passing methods, what are all of the values of the variables value and list after each of the three calls to swap?
a. passed by value: The values remain the same
b. passed by reference: value = 2 list= {3,1,5,7,9}
c. passed by value-result: value = 2 list = {3,1,5,7,9}
8. Some C puzzles involving expression evaluation and assignment:
a. What does this do:
int a=5, b=10;
f( (a,b) );
The inner expression uses the weird comma operator in C. The result of a comma-separated list of expressions in C is the value of the rightmost expression. So 10 (the value of b) is passed to the function f (which presumably expects a single int argument).
b. One of these expressions is valid in C, the other is undefined. Explain.
int j=5;
if ( j++ == ++j ) ....
if ( j++ & ++j ) ...
Expressions involving two or more modifications to the same variable are generally undefined in C. (There is an inscrutable definition for this in the Standard involving the concept of "sequence points". Not for the faint of heart...) The first statement will clearly cause problems. The order of the increments is not specified. In the second expression, because of short-circuit evaluation of the boolean AND operator (&) a very similar
expression is well-defined because the first increment MUST be evaluated first, then the second (only if the first is TRUE).
c. What's the problem here?
int y;
double x, z;
x = y = z = 3.1415;
Suggested solution:
There is a hidden truncation lurking in here. Because = is right associative, first 3.1415 is assigned to z, then the same value is assigned to the int y, causing a truncation. This truncated value (3.0) is then assigned to the floating-point variable x.