Sei sulla pagina 1di 12

ITECH5403 Comparative Programming Languages

School of Science, Engineering and Information Technology

ITECH5403 - Lab 3 – Names, Bindings and Scope

Introduction

Today we'll work on some review questions and exercises relating to names, bindings and scope. It's important that you
understand the difference between static and dynamic binding and scoping rules – as well as when it's appropriate to use
the stack or the heap for data storage.

The exam for this course will consist of a selection of questions from each week's lab (80%) and related questions which
help to tie different areas of programming languages together (20%). If you can answer these questions in the lab – you
can answer them in the exam! Remember – in these labs you aren't expected to know every single answer from memory
– sometimes it's best to do a little research / reading / re-reading of materials and come up with a great, and correct,
answer rather than just 'taking a stab' at the question and hoping you're right!

Review Questions

1. What are the design issues for names? [Q1]

Are the names case sensitive?

Do they have a maximum length?

Are there special reserved words or keywords?

What symbols are legal or illegal for the name to contain.

What symbols are legal or illegal for the name to start with (i.e. reserved prefixes).

2. In what way are reserved words better than keywords? [Q3]

Reserved words are better than keywords because reserved words cannot be redefined, whereas keywords CAN be
redefined. This may cause problems if, for example, you redefine a keyword to have an altered meaning, but this is not
widely documented public knowledge to the people using those keywords, who would (rightly) believe that the keywords
held their original meaning!

3. What is the l-value of a variable? What is the r-value? [Q6]

The l-value of a variable is the memory address of that variable.

The r-value of a variable is the actual value held at the l-value's memory address.

4. Define binding and binding time. What are the different times that binding can take place in a
program? [Q7+8]

A binding is an association between an attribute and an entity, such as between a variable and its type of value, or
between an operation and a symbol. The time at which a binding takes place is called the binding time.

CRICOS Provider No. 00103D Insert file name here Page 1 of 12


ITECH5403 Comparative Programming Languages

School of Science, Engineering and Information Technology

Bindings can take place at a number of different stages / times, such as at:

Language design time,


Language implementation time,
Compile time,
Load time,
Link time, or
Run time.

5. Define static binding and dynamic binding. Give one example of each. [Q9]

A binding is static is it first occurs before run time begins and remains unchanged throughout program execution. For
example, a constant may be defined as const int daysInWeek = 7; - the daysInWeek constant will have its type determined
at compilation and it will be statically fixed to being an int, with a specified value, as a specified (albeit relative) memory
address during compilation.

If the binding first occurs during run time or can change in the course of program execution, it is called dynamic
binding. For example, if a program declared (but did not instantiate) an array of objects, then asked the user to choose
[I]nteger or [F]loat, then depending on the choice made by the user at runtime the array could be instantiated as an
array of (for example) three objects of the desired type with either:

myArray = new Integer[3]; or

myArray = new Float[3];

6. Define static, stack-dynamic, explicit heap-dynamic and implicit heap-dynamic variables. What
are the advantages and disadvantages of each? [Q12]

Static variables are those that are bound to memory cells before program execution begins, and remain bound to those
same memory cells until program execution terminates. Statically bound variables have several valuable applications in
programming - for example, globally accessible variables (global variables) are often used throughout the execution of a
program, thus making it necessary to have them bound to the same storage location during executions. However, the
disadvantage is that the type cannot be changed during runtime at all, ever!

Stack-dynamic variables are those whose storage bindings are created when their declaration statements are elaborated,
but whose types are not statically bound. The main advantage of Stack-dynamic variables are that, to be useful (at least
in most cases), recursive subprograms require some form of dynamic local storage so that each active copy of the
recursive subprogram has its own version of the local variables - this is made possible by stack-dynamic variables. The
main disadvantage of stack-dynamic variables, relative to static variables, is the runtime overhead of the dynamic
allocation and deallocation - and the possibly slower accesses because indirect addressing is required.

Explicit heap-dynamic variables are nameless (abstract) memory cells that are allocated and deallocated by explicit run-
time instructions written by the programmer. These variables, which are allocated from and deallocated back to the heap,
can only be referenced through pointer or reference variables. Advantages are that it makes it possible construct dynamic
structures such as linked lists and trees which can grow and shrink at runtime, and that we have full access to large
amounts of RAM on the target machine, which we cannot get via the stack. However, the downsides are the difficulty in
using pointer and reference variables correctly - failure to correctly allocate and deallocate memory can lead to memory

CRICOS Provider No. 00103D Page 2 of 12


ITECH5403 Comparative Programming Languages

School of Science, Engineering and Information Technology

leaks!, and the complexity/time-cost of managing all these allocation and deallocations - this is a hidden cost that occurs
'behind the scenes' because heap management must take place by the operating system.

Implicit heap-dynamic variables are bound to heap storage only when they are assigned values. In fact, all their
attributes are bound every time they are assigned. For example, consider the following JavaScript assignment statement:

highTemps = [74, 84, 86, 90, 71];

Regardless of whether the variable named highTemps was previously used in the program or what it was used for - it is
now an array of five numeric values.The advantage of such variables is that they have the highest degree of flexibility,
allowing highly generic code to be written without having to worry about explicit deallocation (they'll deallocate when
they go out of scope!). The disadvantages of implicit heap-dynamic variables include the overhead of maintaining the
dynamic attributes such as array subscript types and ranges, as well as some potential loss of error detection by the
compiler.

7. What is the referencing environment of a statement [Q16]

The referencing environment of a statement is the collection of all variables that are visible in the statement. In a static-
scoped language, this is the set of variables declared in its local scope plus the set of variables in any ancestor scopes
that are visible.

In such a language, the referencing environment statement is needed while that statement is being compiled, so code and
data structures can be created to allow references to variables from other scopes during runtime. In other words - the
referencing environment is required so that we know what variables can be accessed from the current point in the code!

Problem Set

1. Which of the following identifier forms is most readable? Support your decision. [EX1]

SumOfSales
sumOfSales
sum_of_sales
SUMOFSALES

sum_of_sales is probably technically the most readable as each word is separated with an underscore, which makes it
almost as easy to read as plain English. However, sumOfSales is the most usable – because the starting lowercase value
tells us that we're dealing with a variable or object and not a class (which would start with a capital letter), and the lack
of underscores (which require shift + - to insert into text – i.e. a two-ley combo) mean that we don't have to perform the
key-combo everytime we want to write out the variable/object name.

2. Some programming languages are typeless. What are the obvious advantages and disadvantages
of having no types in a language? [EX2]

Advantages of typeless languages are that we don't have to work out what types will work together – the interpreter will
do it for us. Also, we can re-use variable names with different data types easily, i.e.

CRICOS Provider No. 00103D Page 3 of 12


ITECH5403 Comparative Programming Languages

School of Science, Engineering and Information Technology

var foo = 123; foo = "Hello!"; foo = 1.23; etc.

Disadvantages are that we may have to be a lot more careful in combining data of different types when we cannot
guarantee that the types are compatible, for example, multiplying a numeric value by a string would not throw an error
until runtime in a typeless language, while this would be caught automatically and far earlier at compile time in a
strongly typed language.

3. Assume the following JavaScript program was interpreted using static-scoping rules. What value of x
is displayed in function sub1? Under dynamic-scoping rules, what value of x is displayed in function
sub1? [EX7]

var x;
function sub1() { document.write("x = " + x + "<br />"); }

function sub2() { var x; x = 10; sub1(); }

x = 5;
sub2();

4. Consider the following Python program: Complete answers


are here.
x = 1;
y = 3;
z = 5;
#P1

def sub1(): P1: x, y and z are defined globally and can be


a = 7;
y = 9; both referenced and assigned.
z = 11;
#P2

def sub2():
global x; P2: x can be referenced but not assigned. y
a = 13; and z are local to sub1.
x = 15;
w = 17;
#P3

def sub3(): P3: x is global for reference and assignment,


nonlocal a; a and w are local to sub2
a = 19;
b = 21;
z = 23;
#P4
P4: a is nonlocal (we use the sub2 version), b
sub3(); is local to sub3. Z can be ref'd but not
sub1(); assigned
sub2();

P3:

CRICOS Provider No. 00103D Page 4 of 12

P4:
ITECH5403 Comparative Programming Languages

School of Science, Engineering and Information Technology

List all the variables, along with the program units where they are declared, that are visible at the points P1
through P4 assuming static scoping is used. You can use the following website to help answer this
question – but do remember the website won't be available in the exam!
http://www.pythontutor.com/visualize.html#mode=edit

Also, on the python tutor website, be sure to select Language: Python 3.3 from the drop-down (because
Python 2.x does not provide the nonlocal keyword) [EX9]

5. Consider the following program, written in JavaScript-like syntax:


// main program
var x, y, z;
function sub1() {
var a, y, z;
. . .
}
function sub2() {
var a, b, z;
. . .
}
function sub3() {
var a, x, w;
. . .
}

Given the following calling sequences and assuming that dynamic scoping is used, what variables are
visible during execution of the last subprogram activated? Include with each visible variable the name
of the unit where it is declared: [EX12]

a. main calls sub1; sub1 calls sub2; sub2 calls sub3.


b. main calls sub1; sub1 calls sub3.
c. main calls sub2; sub2 calls sub3; sub3 calls sub1.
d. main calls sub3; sub3 calls sub1.
e. main calls sub1; sub1 calls sub3; sub3 calls sub2.
f. main calls sub3; sub3 calls sub2; sub2 calls sub1.

The referencing environment of a dynamically scoped


language is the set of locally declared variables, plus the
variables of all other subprograms that are currently active.
However, variables declared outside the current referencing
environment will be hidden if there are variables with the
same name inside the current referencing environment:

CRICOS Provider No. 00103D Page 5 of 12


ITECH5403 Comparative Programming Languages

School of Science, Engineering and Information Technology

a.) main has x, y and z. Visible: main x, main y, main z.


main calls sub1, sub1 has local a, y and z. Visible: sub1 a, sub1 y, sub1 z, main x.
sub1 calls sub2, sub2 has local a, b and z. Visible: sub2 a, sub2 b, sub2 z, sub1 y, main x.
sub2 calls sub3, sub3 has local a, x and w.

Final visibles: sub3 a, sub3 x, sub3 w, sub2 b, sub2 z, sub1 y.

b.) main has x, y and z. Visible: main x, main y, main z.


main calls sub1 called, and has local a, y and z. Visible: sub1 a, sub1 y, sub1 z, main x
sub1 calls sub3, sub3 has local a, x and w.

Final visibles: sub3 a, sub3 x, sub3 w, sub1 y, sub1 z.

c.) main has x, y and z. Visible: main x, main y, main z.


main calls sub2, sub2 has local a, b and z. Visible: sub2 a, sub2 b, sub2 z, main x, main y.
sub2 calls sub3, sub3 has local a, x and w. Visible: sub3 a, sub3 x, sub3 w, sub2 b, sub2 z, main y.
sub3 calls sub1, sub1 has local a, y and z.

Final visibles: sub1 a, sub1 y, sub1 z, sub3 x, sub3 w, sub2 b.

d.) main has x, y and z. Visible: main x, main y, main z.


main calls sub3, sub3 has local a, x and w. Visible: sub3 a, sub3x, sub3 w, main y, main z.
sub3 calls sub1, sub1 has local a, y and z.

Final visibles: sub1 a, sub3x, sub3 w, sub1 y, sub1 z.

e.) main has x, y and z. Visible: main x, main y, main z.


main calls sub1, sub1 has local a, y and z. Visible: sub1 a, sub1 y, sub1 z, main x.
sub1 calls sub3, sub3 has local a, x and w. Visible: sub3 a, sub3 x, sub3 w, sub1 y, sub1 z.
sub3 calls sub2, sub2 has local a, b and z.

Final visibles: sub2 a, sub2 b, sub2 z, sub3 x, sub3 w, sub1 y.

f.) main has x, y and z. Visible: main x, main y, main z.


main calls sub3, sub3 has local a, x and w. Visible: sub3 a, sub3x, sub3 w, main y, main z.
sub3 calls sub2, sub2 has local a, b and z. Visible: sub2 a, sub2 b, sub2 z, sub3 x, sub3 w, main y.
sub2 calls sub1, sub1 has local a, y and z.

Final visibles: sub1 a, sub1 y, sub1 z, sub2 b, sub3 x, sub3 w.

CRICOS Provider No. 00103D Page 6 of 12


ITECH5403 Comparative Programming Languages

School of Science, Engineering and Information Technology

6. Write a JavaScript script that has subprograms nested three deep and in which each nested
subprogram references variables defined in all of its enclosing subprograms. Use this link to help you
get started: http://javascript.info/tutorial/functions-declarations-and-expressions [EX3]

<!DOCTYPE html>
<html>
<head>
<script>
// Initial global variables in main referencing environment
var w = 0, x = 1, y = 2, z = 3;

function sub1() {
var x = 4; // Overwrite x with local copy
alert("In sub1 - w is: " + w + ", x is: " + x + ", y is: " + y + ", z is: " + z);

function sub2() {
var y = 5; // Overwrite y with local copy
alert("In sub2 - w is: " + w + ", x is: " + x + ", y is: " + y + ", z is: " + z);

function sub3() {
var z = 6; // Overwrite z with local copy
alert("In sub3 - w is: " + w + ", x is: " + x + ", y is: " + y + ", z is: " + z);
}
sub3(); // Call sub3 from within sub2

} // End of sub2
sub2(); // Call sub2 from within sub1

} // End of sub1
</script>
</head>

<body>
<h1>JavaScript Nested Functions / Closure Test</h1>
<button type="button" onclick="sub1()">Do Stuff!</button>
</body>
</html>

CRICOS Provider No. 00103D Page 7 of 12


ITECH5403 Comparative Programming Languages

School of Science, Engineering and Information Technology

7. Using Code::Blocks or a similar IDE (Visual Studio etc.), create a new C project (NOT C++) that
declares a global int called x, and write a function that includes the following sequence of statements:

x = 21;
int x;
x = 42;

Run the program and explain the results. Rewrite the same code in C++ and Java and compare the
results. [EX5]

C example:

#include <stdio.h>
#include <stdlib.h>

int x; // Globally declare but do not initialise x

void func() {
x = 21;
printf("After assignment in func, x address is: %p with value: %d\n", &x, x);

int x = 42;
printf("After local x dec'd in func, x address is: %p with value: %d\n", &x, x);
}

int main() {
printf("In main scope, x address is: %p with value: %d\n", &x, x);
func();

// Get a key then bail (used to keep the console window open)
getch();
return 0;
}

Variable gets hidden by variable with same name inside local scope of function. Memory addresses show that
these are distinct variables.

CRICOS Provider No. 00103D Page 8 of 12


ITECH5403 Comparative Programming Languages

School of Science, Engineering and Information Technology

C++ Example:

#include <iostream>
#include <stdio.h>
using namespace std;

int x; // Globally declare but do not initialise x

void func() {
x = 21;
printf("After assignment in func, x address is: %p with value: %d\n", &x, x);

int x = 42;
printf("After local x dec'd in func, x address is: %p with value: %d\n", &x, x);
}

int main() {
printf("In main scope, x address is: %p with value: %d\n", &x, x);
func();

// Get a key then bail (used to keep the console window open)
getchar();
return 0;
}

Same behaviour as in C!
Java example:

public class Main {

// Global int property declared, will be auto-initialised to zero


int x;

public static void main(String[] args) {


new Main();
}

CRICOS Provider No. 00103D Page 9 of 12


ITECH5403 Comparative Programming Languages

School of Science, Engineering and Information Technology

// Constructor must perform work otherwise declaration of 'int x' above must be static if
executed in 'main' method
public Main() {
System.out.println("In constructor, x address is: " + ((Object)x).hashCode() + "
with value: " + x);
func();
}

public void func() {


x = 21;
System.out.println("After assignment in func, x address is: " + ((Object)x).hashCode()
+ " with value: " + x);

int x = 42;
System.out.println("After new x declared in func, x address is: " +
((Object)x).hashCode() + " with value: " + x);

Output:
In constructor to access class property x, address is: 0 with value: 0
After assignment in func, x address is: 21 with value: 21
After new x declared in func, x address is: 42 with value: 42

Same behaviour as in C! They all work in the same manner! I'm not entirely sure this is what we're meant to be
proving asides from that variable hiding works in local scopes…

8. Write three functions in C++: one that declares a large array statically, one that declares the same
large array on the stack, and one that creates (and frees!) the same large array on the heap. Call each
of the subprograms a large number of times (at least 100,000) and output the time required by each.
Explain the results. [EX7]

You can use the following code as the basis for your timer:

<Code removed – is included in full example below>

Answer:

#include <iostream>
#include <time.h>

using namespace std;

// Declare our counters


static clock_t startTime, endTime, durationInMS;

void createStaticArray()
{
// 100,000 element static array of ints
static int foo[100000];

// Do something with them so they don't get optimised away

CRICOS Provider No. 00103D Page 10 of 12


ITECH5403 Comparative Programming Languages

School of Science, Engineering and Information Technology

foo[0] = 123;
foo[99999] = 456;
int sum = foo[0] + foo[99999];
}

void createStackArray()
{
// 100,000 element static array of ints
int bar[100000];

// Do something with them so they don't get optimised away


bar[0] = 123;
bar[99999] = 456;
int sum = bar[0] + bar[99999];
}

void createHeapArray()
{
// 100,000 element static array of ints
int *baz = new int[1000000];

// Do something with them so they don't get optimised away


*baz = 123;
*(baz + 99999) = 456;
int sum = *baz + *(baz + 99999);

delete[] baz;
}

void printTimings(string testName)


{
// Get the end time
endTime = clock();

// Calculate the duration in milliseconds


// Note: Technically, this is CPU time not actual time elapsed so function
// sleeps will not be measured - but this is acceptable for our purposes.
durationInMS = endTime - startTime;

cout << "----- " << testName << " -----" << endl;
cout << "Start time : " << startTime << endl;
cout << "End time : " << endTime << endl;
cout << "Duration in Milliseconds: " << durationInMS << endl << endl;
}

int main()
{
// Static array test
startTime = clock();
for (int loop = 0; loop < 10000000; loop++)
{
createStaticArray();
}
printTimings("Static Array Test");

// Stack array test


startTime = clock();
for (int loop = 0; loop < 10000000; loop++)
{
createStackArray();
}

CRICOS Provider No. 00103D Page 11 of 12


ITECH5403 Comparative Programming Languages

School of Science, Engineering and Information Technology

printTimings("Stack Array Test");

// Heap array test


startTime = clock();
for (int loop = 0; loop < 10000000; loop++)
{
createHeapArray();
}
printTimings("Heap Array Test");

getchar();
return 0;
}

Look how quick the static array test is! 21ms! This is because the static array is only ever allocated once and then re-
used. However, this measurement might be off as the static array is allocated before we even start the main program
execution, because that's how static allocation works.

The stack array test is almost 290x slower than the static test it allocates the array each time, but stack allocation and
deallocation is fast!

The heap test takes the longest (1656x slower than static, and almost 6x slower than stack allocation) because it has to
dynamically allocate and deallocate tha large array on the heap each time, which is slower than via the stack (stack
deallocation is incredibly quick because we just 'pop' the stack to revert it to the previous state).

CRICOS Provider No. 00103D Page 12 of 12

Potrebbero piacerti anche