Вы находитесь на странице: 1из 34

Variables and Storage

A simple storage model. Simple and composite variables.

Copy semantics vs reference semantics.


Lifetime.

3-1

Variables and Storage (contd)


Commands.

Expressions with side effects.


Implementation notes.

Storage for global and local variables

3-2

An abstract model of storage (1)


In functional/logic PLs (as in mathematics), a variable stands for a fixed but unknown value. In imperative/OO PLs, a variable is a container for a value, which may be inspected and updated as often as desired. Such a variable can be used to model a real-world object whose state changes over time.

3-3

An abstract model of storage (2)


To understand such variables, assume a simple abstract model of storage:
A store is a collection of storage cells. Each storage cell has a unique address.

unallocated cells
7 true 3.14 allocated cells

Each storage cell is either allocated or unallocated.


Each allocated storage cell contains either a simple value or undefined.

undefined

3-4

Simple vs composite variables


A simple value is one that can be stored in a single storage cell (typically a primitive value or a pointer). A simple variable occupies a single allocated storage cell. A composite variable occupies a group of allocated storage cells.

3-5

Simple variables
When a simple variable is declared, a storage cell is allocated for it. Assignment to the simple variable updates that storage cell. At the end of the block, that storage cell is deallocated. Animation (Ada):
declare n: Integer; begin n := 0; n := n+1; end;

1 0 ?

3-6

Composite variables (1)


A variable of a composite type has the same structure as a value of that type. For instance:
A record variable is a tuple of component variables. An array variable is a mapping from an index range to a group of component variables.

The component variables can be inspected and updated either totally or selectively.

3-7

Composite variables (2)


Animation (Ada):
declare type Date is record y: Year_Number; m: Month; d: Day_Number; end record; xmas, today: Date; begin xmas.d := 25; xmas.m := dec; xmas.y := 2004; today := xmas; end;

xmas today today xmas xmas today 2004 ? 2004 ? ? ? ? 2004 dec ?dec dec ? ? ? 2525 ? 25 ? ?
3-8

Total vs selective update


Total update of a composite variable means updating it with a new (composite) value in a single step:
today := xmas;

Selective update of a composite variable means updating a single component:


today.y := 2004;

3-9

Copy semantics vs reference semantics


What exactly happens when a composite value is assigned to a variable of the same type? Copy semantics: All components of the composite value are copied into the corresponding components of the composite variable. Reference semantics: The composite variable is made to contain a pointer (or reference) to the composite value.

C and Ada adopt copy semantics.


Java adopts copy semantics for primitive values, but reference semantics for objects.
3-10

Example: Ada copy semantics (1)


Declarations:
type Date is record y: Year_Number; m: Month; d: Day_Number; end record; dateA: Date := (2004, jan, 1); dateB: Date;

Effect of copy semantics:


dateB := dateA; dateB.y := 2005;

dateA dateB dateA dateB 2004 ? 2005 2004 2004 jan jan jan ? jan 1 1 1 ? 1
3-11

Example: Java reference semantics (1)


Declarations:
class Date { int y, m, d; public Date (int y, int m, int d) { } } Date dateR = new Date(2004, 1, 1); Date dateS = new Date(2004, 12, 25);

Effect of reference semantics:


dateS = dateR;

dateR dateS

2004 1 1

2004 12 25
3-12

Example: Java reference semantics (2)


We can achieve the effect of copy semantics in Java by cloning:
Date dateR = new Date(2004, 4, 1); dateT = dateR.clone();

3-13

Lifetime (1)
Every variable is created (or allocated) at some definite time, and destroyed (or deallocated) at some later time when it is no longer needed. A variables lifetime is the interval between its creation and destruction. A variable occupies storage cells only during its lifetime. When the variable is destroyed, the storage cells that it occupied may be deallocated (and subsequently allocated for some other purpose).

3-14

Lifetime (2)
A global variables lifetime is the programs run-time. It is created by a global declaration. A local variables lifetime is an activation of a block. It is created by a declaration within that block, and destroyed on exit from that block.

3-15

Commands
A command (or statement) is a PL construct that will be executed to update variables. Commands are characteristic of imperative and OO (but not functional) PLs.

Forms of commands:
skips assignments

procedure calls
sequential commands conditional commands iterative commands.
3-16

Skips
A skip is a command with no effect.

Typical forms:
; in C and Java null; in Ada.

Skips are useful mainly within conditional commands.

3-17

Assignments
An assignment stores a value in a variable.

Single assignment:
V = E; in C and Java V := E; in Ada

the value of expression E is stored in variable V. Multiple assignment:


V1 = = Vn = E; in C and Java

the value of E is stored in each of V1, , Vn.

3-18

Procedure calls
A procedure call achieves its effect by applying a procedure to some arguments. Typical form:
P(E1, , En);

Here P determines the procedure to be applied, and E1, , En are evaluated to determine the arguments. Each argument may be either a value or (sometimes) a reference to a variable. The net effect of the procedure call is to update variables. The procedure achieves this effect by updating variables passed by reference, and/or by updating global variables. (But updating its local variables has no net effect.)
3-19

Sequential commands
Sequential, conditional, and iterative commands (found in all imperative/OO PLs) are ways of composing commands to achieve different control flows. Control flow matters because commands update variables, so the order in which they are executed makes a difference. A sequential command specifies that two (or more) commands are to be executed in sequence. Typical form:
C1 C2

command C1 is executed before command C2.

3-20

Conditional commands
A conditional command chooses one of its subcommands to execute, depending on a condition. An if-command chooses from two subcommands, using a boolean condition.

A case-command chooses from several subcommands.

3-21

If-commands (1)
Typical forms (Ada and C/Java, respectively):
if E then C1 else C2 end if; if (E) C1 else C2
E must be of type Boolean

if E yields true, C1 is executed; otherwise C2 is executed.

3-22

If-commands (2)
Generalisation to multiple conditions (in Ada):
if E1 then C1 elsif E2 then C2 elsif En then Cn else C0 end if;
E1, , En must be of type Boolean

if E1, , Ei-1 all yield false but Ei yields true, then Ci is executed; otherwise C0 is executed.
3-23

Case-commands (1)
In Ada:
case E is when v1 => C1 when vn => Cn when others => C0 end case;
E must be of some primitive type other than Float

v1, , vn must be distinct values of that type

if the value of E equals some vi, then Ci is executed; otherwise C0 is executed.


3-24

Case-commands (2)
In C and Java:
switch (E) { case v1: C1 case vn: Cn default: C0 }
E must be of integer type

v1, , vn must be integers, not necessarily distinct

if the value of E equals some vi, then Ci, , Cn, C0 are all executed; otherwise only C0 is executed.
3-25

Example: Ada case-command


Code:
today: Date; case today.m is when jan => put("JAN"); when feb => put("FEB"); when nov => put("NOV"); when dec => put("DEC"); end case;

3-26

Example: Java switch-command

breaks are essential


3-27

Example: Java switch-command (contd)

breaks are essential

3-28

Iterative commands
An iterative command (or loop) repeatedly executes a subcommand, which is called the loop body. Each execution of the loop body is called an iteration. Classification of iterative commands:
Indefinite iteration: the number of iterations are not predetermined. Definite iteration: the number of iterations are predetermined.

3-29

Indefinite iteration
Indefinite iteration is most commonly supported by the while-command. Typical forms (Ada and C/Java):
while E loop C end loop; while (E) C

3-30

Definite iteration
Definite iteration is characterized by a control sequence, a predetermined sequence of values that are successively assigned (or bound) to a control variable. Ada for-command:
for V in R loop C end loop;
R must be of some primitive type other than Float

the control sequence consists of all values in the range R, in ascending order.

3-31

Implementation notes
Each variable occupies storage space throughout its lifetime. That storage space must be allocated at the start of the variables lifetime (or before), and deallocated at the end of the variables lifetime (or later). The amount of storage space occupied by each variable depends on its type. Assume that the PL is statically typed: all variables types are declared explicitly, or the compiler can infer them.

3-32

Storage for global and local variables (1)


A global variables lifetime is the programs entire runtime. So the compiler can allocate a fixed storage space to each global variable. A local variables lifetime is an activation of the block in which the variable is declared. The lifetimes of local variables are nested. So the compiler allocates storage space to local variables on a stack.

3-33

Storage for global and local variables (2)


At any given time, the stack contains several activation frames. Each activation frame contains enough space for the local variables of a particular procedure. An activation frame is:
pushed on to the stack when a procedure is called popped off the stack when the procedure returns. housekeeping data local variables

3-34

Вам также может понравиться