Download presentation
1
Variables Six properties: Binding times of properties:
name address type value lifetime scope Binding times of properties: language specification time language implementation time compile time run time Broad classification: static dynamic
2
1. Name Syntax of language specifies valid names.
Languages used to limit length of names BASIC (1978): [A-Z]([0-9]) Fortran77: 6 characters Fortran95: 31 characters Java, C#: no limit Restrictions: keywords have special meaning (e.g. ‘for’) reserved words cannot be used as names generally keywords are reserved
3
2. Address The memory address at which the value associated with the name is stored. This is called the l-value (because it is the value used on the left hand side of an assignment operator). In Scheme terms, an unevaluated symbol. A given name can be associated with multiple addresses during program execution (e.g. parameters of a recursive function, an instance variable defined in a multiply-instantiated class). Aliasing occurs when many variables share an address.
4
3. Type The type of a variable determines the set of values which can be associated with the name. We will return to type binding and type checking.
5
Aside: binding times of types
The binding time of a set of values to a type differs across languages. In Java the size and representation for types is written into the language specification. every Java implementation is guaranteed to have the same range of values for the primitive types. In C the binding of a set of value to types is left to implementation time. different implementations can (and do) make different decisions implication is that the very same program can behave differently on different platforms.
6
Binding types to names (1)
Explicit vs. implicit an explicit declaration specifies the type of a variable an implicit declaration is a language convention giving name-type mappings Fortran: “If the identifier begins with one of the letters I, J, K, L, M or N, or their lowercase versions, it is implicitly declared to be Integer type, otherwise it is implicitly declared to be Real type.” [p. 213] Perl: different namespaces for different types $ implies scalar @ implies array % implies hash
7
Binding types to names (2)
Static vs. dynamic with static binding the type of a variable is known at compile time (e.g. C, C++, Java) with dynamic binding the type of a variable is not known until run time (e.g. Scheme, JavaScript), and can change during the execution of a program [pg. 214]: list = [10.2, 3.5]; list = 47;
8
Binding types to names (3)
Type inferencing (ML) ML derives the types of all expressions from the types of their constituent parts. ML (with very few exceptions) does not require any type declarations, and yet all expressions are fully typed at compile time. ML uses type variables to express generic types (e.g. ’a and ”a).
9
4. Value The r-value of the variable (because it is the value used on the right hand side of an assignment operator). In Scheme terms, the value retrieved from symbol lookup in an environment. This is the contents of a block of memory cells, whose starting address is the l-value of the variable, whose size and interpretation are determined by the type of the variable. Sometimes we refer to this block of memory, typically many bytes large, simply as the “memory cell” of a variable.
10
Aside: memory footprint & representation
The type of a variable determines two very important things: the amount of memory allocated to the variable the representation scheme used to write/read bit patterns into/from memory. Consider the type short in C. Using the default ‘cc’ compiler on pollux, we find that a short occupies 8 bits; integers are stored using the 2’s complement representation scheme.
11
Anatomy of a short The range of values we can store in a short is -128 to +127: BIT PATTERN DECIMAL VALUE
12
Anatomy of an int The range of values we can store in an int is to : BIT PATTERN DECIMAL VALUE
13
What happens here? int i = 128; short s = i;
14
5. Lifetime “The lifetime of a variable is the time during which the variable is bound to a specific memory location.” [p. 219] “…the lifetime of a variable begins when it is bound to a specific cell and ends when it is unbound from that cell.” [p. 219] Four categories static stack-dynamic explicit heap-dynamic implicit heap-dynamic
15
Memory organization STATIC code & static data STACK local data:
AVAILABLE MEMORY STACK local data: invocation records HEAP dynamic data
16
static variables Bound to a memory location prior to execution.
No run-time allocation needs to occur: efficient. Persistent: variable persists throughout execution of a program.
17
Example (C) #include “stdio.h”; int counter() { static int k = 0;
return ++k; } int main() { printf(“Counter is %d \n”,counter()); return 0; /* OUTPUT IS: Counter is 1 Counter is 2 */
18
Notes about example static variable k is allocated space in the static segment allocation happens once k’s lifetime is the that of the entire program k’s value persists from call to call
19
stack dynamic variables
“storage bindings are created when their declaration statements are elaborated, but whose types are statically bound” [p. 220] Allocated on the run-time stack
20
Example (C) #include “stdio.h”; int counter() { int k = 0; return ++k;
} int main() { printf(“Counter is %d \n”,counter()); return 0; /* OUTPUT IS: Counter is 1 */
21
Notes about example stack-dynamic variable k is allocated space in the stack segment allocation happens each time function is called k’s lifetime is the that of the function invocation k’s value does not persist from call to call: it is reinitialized on each function execution
22
explicit heap-dynamic variables
anonymous (nameless) variables created at runtime, allocated on the heap, and accessible only via indirection (a pointer) Example [p. 221] int *intnode; // Create a pointer ... intnode = new int; // Create the heap-dynamic variable delete intnode; // Deallocate the heap-dynamic variable // to which intnode points
23
Example (Java) public class Count private int k; public Count() {
} public int counter() { return ++k; public static void main(String [] args) { Count c = new Count(); System.out.println(“Counter is ”+c.counter()); /* OUTPUT IS: Counter is 1 Counter is 2 */
24
Notes about example instance variable k is allocated space in the heap segment allocation happens each time object is created k’s lifetime is the that of its object k’s value persists from call to call of the method many different independent k’s can co-exist
25
implicit heap-dynamic variables
automatic heap-allocation JavaScript, [pg. 214]: list = [10.2, 3.5]; list = 47; Scheme all allocation is done on heap cons allocates a pair environments are allocated on heap (so no runtime stack is needed for function calls).
26
Example (Scheme) (define count1 (lambda () (let ((k 0))
(set! k (+ k 1)) k ))) (define count2 (display (count1)) (newline) (display (count2)) (newline) /* OUTPUT IS: 1 2 */
27
Environment diagrams (drawn on board)
28
Notes about example in count1 k is initialized each time function is called in count2 k is initialized when the function is defined
29
Exercise How do you define a Scheme function which can dynamically generate counter functions, each with its own independent counter?
30
counterMaker (define counterMaker (lambda () (let ((k 0))
(set! k (+ k 1)) k )))) (define c1 (counterMaker)) (define c2 (counterMaker)) (c1) (c1) (c1) (c2) (c2) (c1) (c2)
31
6. Scope “The scope of a variable is the range of statements in which the variable is visible. A variable is visible in a statement if it can be referenced in that statement.” Two basic approaches: static scoping dynamic scoping
32
Static scope Static scoping (also called lexical scoping): the scope of a variable is determined by the static (lexical) structure of the program. scope determined by lexical nesting some languages allow nested blocks we’ve seen examples in C and Java some languages allow nested functions C/C++/Java do not allow this Scheme/ML do
33
Dynamic scope dynamic scope scope determined by (dynamic) call history
we will see an example soon
34
Why do we care? Obviously important for our understanding of programs.
More importantly, we use the scoping of variables to support encapsulation. Strong encapsulation lets us build robust components: grants access to those components which need it denies access to all other components
35
Collection classes Each collection defines its own Iterator.
Each collection needs to keep its implementation details private. Each iterator is defined as a separate class (so it can be instantiated independently of the class). Each iterator encapsulates iteration logic for a specific collection. It must know the implementation details in order to serve as the bridge between clients of the collection and the internal workings of that collection. How do we grant access to Iterator classes while denying access to others?
36
Inner classes Java’s Collection classes
concrete collection class must hide its implementation must provide Iterator Iterator must know implementation details Inner class structure embeds Iterator definition within scope of collection class Iterator can access internals of collection without collection having to break encapsulation
37
Nested functions Create nested scopes to hide bindings
Allows us to hide helper functions (similar to what inner classes let us do): (define fact (letrec ((helper (lambda (n acc) (if (= n 0) acc (helper (- n 1) (* n acc)))))) (lambda (n) (helper n 1))))
38
Examples comparing static and dynamic scope
Example in C-like language Example in Scheme-like language
39
Dynamic vs. static scope: C-like language
int a = 3; void foo(){ printf(“a has value %d \n”,a); } void bar(){ int a = 5; foo();} foo(); // what does this print? bar(); // what does this print?
40
With static scope C is statically scoped, so the output will be:
int a = 3; void foo(){ printf(“a has value %d \n”,a); } void bar(){ int a = 5; foo();} void abc(){ int a = 7; foo();} foo(); // what does this print? bar(); // what does this print? abd(); // what does this print? C is statically scoped, so the output will be: a has value 3
41
With dynamic scope If C were dynamically scoped, the output would be:
int a = 3; void foo(){ printf(“a has value %d \n”,a); } void bar(){ int a = 5; foo();} void abc(){ int a = 7; foo();} foo(); // what does this print? bar(); // what does this print? abd(); // what does this print? If C were dynamically scoped, the output would be: a has value 3 a has value 5 a has value 7
42
Languages with dynamic scope
Common Lisp and Perl give the programmer the option of using either dynamic or static scope.
43
Dynamic vs. static scope: Scheme-like language
(define a 3) (define f (lambda () a)) (define g (lambda (a) (f))) (f) (g 7)
44
Environment: (define a 3) a 3
45
Environment: (define a 3) (define f (lambda () a )) () a a 3 f
46
Environment: (define a 3) (define f (lambda () a )) (define g
47
Environment during evaluation of (f):
(define a 3) (define f (lambda () a )) (define g (lambda (a) (f) () a (a) a 3 (f) f g (f) => 3 a => 3 static link dynamic link
48
Environment during evaluation of (g 7):
(define a 3) (define f (lambda () a )) (define g (lambda (a) (f) (g 7) () a (a) a 3 (f) f g (g) a 7 (f) static link dynamic link => 3 a => 7
49
Questions?
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.