Expressions and Assignment Statements
Introduction

Expressions are the fundamental means of specifying computations in a programming language

To understand expression evaluation, need to be familiar with the orders of operator and operand evaluation

Essence of imperative languages is dominant role of assignment statements

The purpose of an assignment statement is to change the value of a variable.
Arithmetic Expressions

Arithmetic evaluation was one of the motivations for the development of the first programming languages

Arithmetic expressions consist of operators, operands, parentheses, and function calls
Arithmetic Expressions: Design Issues

Design issues for arithmetic expressions

operator precedence rules

operator associativity rules

order of operand evaluation

operand evaluation side effects

operator overloading

mode mixing expressions
Arithmetic Expressions: Operators

A unary operator has one operand

A Unary addition is called the identity operator, has no affect of its operand. In Java, unary plus or minus actually does have an effect when its operand is short or byte, it causes an implicit conversion of that operand to int type.

Unary minus operator can appear at the beginning or anywhere, as long as it is parenthesized. Ex: A+(B) *C

A binary operator has two operands. (Infix in most languages, prefix in some operators of Perl).

A ternary operator has three operands ? : , included in the Cbased languages.
Arithmetic Expressions: Operator Precedence Rules

The operator precedence rules for expression evaluation define the order in which “adjacent” operators of different precedence levels are evaluated

Typical precedence levels

parentheses

unary operators

** (if the language supports it)

*, /

+, 

The precedence of the arithmetic operators of a few common programming languages are as follows: (sorted from the highest to the lowest)

Fortran

Cbased

Ada

**

Postfix ++, 

**, abs

*, /

Prefix ++, , unary +, 

*, /, mod, rem

All +, 
Binary +, 

*, /, %

Unary +, 


Binary +, 

Binary +, 


The (**) operator is exponentiation. The (%) operator of C is exactly like the (rem) of Ada, it takes two integer operands and yield the reminder of 1^{st} divided by 2^{nd}.

The Ada (mod) operator is identical to (rem) when both operands are positive, but can be different when one or both are negative.

The (abs) od Ada is a unary operator that yields the absolute value of its operand.
Arithmetic Expressions: Operator Associativity Rule

The operator associativity rules for expression evaluation define the order in which adjacent operators with the same precedence level are evaluated

Typical associativity rules

Left to right, except **, which is right to left

Sometimes unary operators associate right to left (e.g., in FORTRAN) A**B**C. The right operator is evaluated 1^{st}.

In Ada, exponentiation is non associative, which means that the expression A**B**C is illegal. The expression must be parenthesized to show the desired order. (A**B)**C or A**(B**C)

In VB the exponentiation (^) is left associative.

Fortran unary and binary minus operators have the same precedence, but in Ada and most other common languages, unary minus have precedence over binary minus.
AB (A) –B
Consider the following –A/B , A*B The relative precedence of the unary minus and binary operators are irrelevant. i.e. the order of evalustion of the two operators has no effect on the value of the expression.
But, A**B, has an effect. Fortran, VB and Ada are the oly languages exponentiation operator.In these languages the exponentiation has higher precedence over unary minus. So, A**B (A**B)
If the unary operator appears at positions other than at the left of the expression, it must be parenthesized, in order to give it highest precedence.
There is one situation where the precedence of a unary operator can be confusing. N Ada, the precedence of unary minus is lower than that of (mod),so expression 17 mod 5 is equivalent to –(17 mod 5) which evaluated to 2, rather than 3, which would be the result if unary minus had higher precedence than (mod), as it does in Cbased languages. (A mod B= (A+k*B) mod B)

Associativity rules for some imperative languages

Language

Associativity rules

Fortran

Left: *, /, +, 
Right: **

Cbased

Left: *, /, %, binary +, binary –
Right: ++, , unary , unary +

Ada

Left: all except **
Nonassociative **


APL is different; all operators have equal precedence and all operators associate right to left
A*B+C if A=3, B=4, C=5, then value =27

Precedence and associativity rules can be overriden with parentheses. Ex: (A+B)*C
Arithmetic Expressions: Conditional Expressions

Conditional Expressions (?:) ternary operator

Cbased languages (e.g., C, C++) expression_1? expression_2: expression_3

An example:
average = (count == 0)? 0 : sum / count

Evaluates as if written like
if (count == 0) average = 0
else average = sum /count
Arithmetic Expressions: Operand Evaluation Order

Operand evaluation order

Variables: fetch the value from memory

Constants: sometimes a fetch from memory; sometimes the constant is in the machine language instruction and not require a memory fetch.

If an operand is parenthesized expression, then all operators it contains must be evaluated before its value can be used as an operand.
Arithmetic Expressions: Potentials for Side Effects

Functional side effects: occurs when a function changes a twoway parameter or a nonlocal variable (nonlocal is a global variable declared outside the function but is accessible in the function).

Consider the expression a+fun(a) if fun does not have the side effect of changing a, then the order of evaluation of the two operands, a and fun(a), has no effect on the value of the expression.

If fun changes a, there I an effect.

Ex: suppose fun returns the value of its argument divided by 2, and changes the value of its parameter to 20.
Suppose we have the following:
a=10;
b=a+fun(a);
if the value of a is fetched first (in the expression evaluation process), its value is 10 and the value of the expression is 15. But if the 2^{nd} operand is evaluated 1^{st}, then the value of the first operand is 20 (because it is changed by the function), and the value of the expression is 25.
Consider the following C program which illustrates the same problem when a function changes a global variable that appears in expression.
The value computed for a in fun2 depends on the order of evaluation of the operands in the expression a+fun1( ) . the value of a will be either 8 or 20.
Functional Side Effects

Two possible solutions to the problem of operand evaluation order.

Write the language definition to disallow functional side effects

No twoway parameters in functions

No nonlocal references in functions

Advantage: it works!

Disadvantage: inflexibility of twoway parameters and nonlocal references

Consider the case of C and C++, which have only functions.

To eliminate the side effects of twoway parameters and still provide subprograms that return more than one value, a new subprogram type that is similar to the procedures of the other imperative languages would be required.

When efficiency is important, using access to global variables to avoid parameter passing is an important method of increasing execution speed. Ex: In compilers, access to data such as the symbol table is commonplace.

Write the language definition to demand that operand evaluation order be fixed

Disadvantage: limits some compiler optimizations

In Java language definition guarantees that operands appear to be evaluated in lefttoright order, eliminating the problem of side effects.
Overloaded Operators

Use of an operator for more than one purpose is called operator overloading

Some are common (e.g., + for int and float Java use it for string catenation. It is accessible, as long as readability and reliability are not suffer)).

Some are potential trouble (e.g., * in C and C++, & if it is binary operator, specifies a bitwise logical AND operation. As a unary operator with a variable as its operand, means address of that variable (addressofoperator)).

Loss of compiler error detection (omission of an operand should be a detectable error). Ex: simple keying error of leaving out 1^{st} operand for a bitwise AND operation can go undetected by the compiler, because it is interpreted as an addressof operator.

Some loss of readability (same symbol for two completely unrelated operations).

Can be avoided by introduction of new symbols (e.g., Pascal’s div for integer division)

C++, Ada, Fortran95, and C# allow userdefined overloaded operators

Potential problems:

Users can define nonsense operations

Readability may suffer, even when the operators make sense
Type Conversions

A narrowing conversion converts a value to a type that cannot store even approximation of all of the values of the original type.
Ex: In Java convert a double to float: the range of double is much larger than that of float
Float to int

A widening conversion converts a value to a type that can include at least approximation of all f the values of the original type.
Ex: converting an int to a float in Java.

Widening conversions are nearly always safe, whereas narrowing conversions are not.

Type conversions can be either explicit or implicit.
Type Conversions: Mixed Mode

A mixedmode expression is one that has operands of different types.

Languages that allow such expressions, much define conventions for implicit operand type conversions because computers usually do not have binary operations that take operands of different types.

A coercion is an implicit type conversion initiated by the compiler.

Disadvantage of coercions:

They decrease in the type error detection ability of the compiler
Consider the following Java code:
int a;
float b, c, d;
…
d=b*a;
Suppose that the second operand of (*) meant to be (c), but wrongly typed (a). because Java allows mixedmode, compiler would not detect as an error. Simply insert code to coerce int operand (a) to float. If the previous case was in Ada, it would be error.

In most languages, all numeric types are coerced in expressions, using widening conversions
Consider the following Java code
byte a, b, c;
…
A=b+c;
The values of (b) and (c) are coerced to int and an int addition is performed, then the sum is converted to byte and put in (a).

In Ada, there are virtually no coercions in expressions
Explicit Type Conversions

Explicit Type Conversions could be widening or narrowing warning message could be issued when explicit narrowing conversion results in significant change to the value of the object being converted.

Called casting in Cbased language

Examples

C: (int) angle

Ada: Float (sum)
Note that Ada’s syntax is similar to function calls
Type Conversions: Errors in Expressions

Causes due to

Inherent limitations of arithmetic e.g., division by zero is disallowed

Limitations of computer arithmetic e.g. overflow or underflow, where the result of an operation cannot be represented in the memory cell where it must be stored (either too large or too small).

Often ignored by the runtime system because it consider exceptions and programs can detect and deal with it.
Relational and Boolean Expressions

Relational Expressions

Use relational operators and operands of various types (simple like integer, or complex like character string ) ( numeric, string, ordinal types)

Evaluate to some Boolean representation

Operator symbols used vary somewhat among languages (!=, /=, .NE., <>, #)

The relational operators always have lower precedence than arithmetic operators.
Ex: a+1>2*b the arithmetic expressions are evaluated 1^{st}.
Relational and Boolean Expressions

Boolean Expressions consist of Boolean variables, Boolean constants, relational expressions, and Boolean operators.

Operands are Boolean and the result is Boolean

Example operators: logical operators
FORTRAN 77 FORTRAN 90 C Ada
.AND. and && and
.OR. or  or
.NOT. not ! not
xor (exclusive OR)
Ada: AND and OR operators have equal precedence.
Cbased: AND has higher precedence than OR.
Relational and Boolean Expressions: No Boolean Type in C

C has no Boolean typeit uses int type with 0 for false and nonzero for true

One odd characteristic of C’s expressions: a < b < c is a legal expression, but the result is not what you might expect:

Left most operator is evaluated, producing 0 or 1

The evaluation result is then compared with the third operand (i.e., c). there is never a comparison between b and c in this expression.
Relational and Boolean Expressions: Operator Precedence

Precedence of Cbased operators (arithmetic, relational, Boolean).
Highest prefix ++, 
unary +, , prefix ++, , !
*,/,%
binary +, 
<, >, <=, >=
=, !=
&&
Lowest 
Short Circuit Evaluation

An expression in which the result is determined without evaluating all of the operands and/or operators

Example: (13*a) * (b/13–1)
If a is zero, there is no need to evaluate (b/131). It is difficult to detected during execution
The value of the Boolean expression
(a>=0) && (b<10) if the 1^{st} relational expression is false, no need to evaluate the 2^{nd}.easily discovered during execution.

Problem with nonshortcircuit evaluation
index = 0;
while (index < length) && (LIST[index] != value)
index++;
Both relational expressions are evaluated.

When index=length, LIST [index] will cause an indexing problem (assuming LIST has length 1 elements)

C, C++, and Java: use shortcircuit evaluation for the usual Boolean operators (&& and ), but also provide bitwise Boolean operators that are not short circuit (& and )

Ada: programmer can specify either (shortcircuit is specified with and then and or else)

Ex: assume List is declared 1..Listlen, the Ada code
Will not cause an error when Key is not in List and Index becomes larger than Listlen.

Shortcircuit evaluation exposes the potential problem of side effects in expressions.

Suppose shortcircuit evaluation is used on an expression and part of the expression that contains a side effect is not evaluated; then the side effect only occur in complete evaluation of the whole expression. If program correctness depends on the side effect, shortcircuit evaluation can result in a serious error.
e.g. (a > b)  ((b++) / 3)

In this expression, b is changed only when a<=b. if the programmer assumed b would be changed every time this expression is evaluated during execution, and the program’s correctness depends on it, the program will fail.
Assignment Statements

Assignment statements provides the mechanism by which the user can dynamically change the bindings of values to variables.

The general syntax
The assignment operator
= FORTRAN, BASIC, PL/I, C, C++, Java
:= ALGOLs, Pascal, Ada
= can be bad when it is overloaded for the relational operator for equality
Instead of typing if(x==y)….we typed if (x=y)…
This si a loss of error detection in the C design of the assignment operation that leads to program errors.
Example of safety deficiencies of C and C++ programs.
Assignment Statements: Conditional Targets

Conditional targets (C, C++, and Java)
(flag)? total : subtotal = 0
Which is equivalent to
if (flag)
total = 0
else
subtotal = 0
Assignment Statements: Compound Operators
Compound Assignment operator

A shorthand method of specifying a commonly needed form of assignment

Introduced in ALGOL; adopted by C

Example
a = a + b
is written as
a += b
Assignment Statements: Unary Assignment Operators

Unary assignment operators in Cbased languages combine increment and decrement operations with assignment

Examples
sum = ++count (count incremented, then assigned to sum) count=count+1;
sum=count;
sum = count++ (Assignment of the value of count to some occurs 1^{st}, then count is incremented, added to sum) sum=count;
count=count+1;
Using of unary increment operator to form a complete assignment statement.
count++ (count incremented)
When two Unary operators apply to the same operands, the association is right
count++ (count incremented then negated) equivalent to –(count++)
Assignment as an Expression

In C, C++, and Java, the assignment statement produces a result and can be used as operands.

This design treats the assignment operator much like any other binary operators, except that it has te side effect of changing its left operand.

An example: in C
while ((ch = getchar())!= EOF){…}
= has lower precedence of relational operator, this why we put ch=getchar() in parenthesis.
ch = getchar() is carried out; the result (assigned to ch) is used as a conditional value for the while statement.
Disadvantages of allowing assignment statement to be operands in expressions, it provides another kind of expression side effect. Makes expressions difficult to read and understand.
MixedMode Assignment

Assignment statements can also be mixedmode, for example
int a, b;
float c;
c = a / b;

The coercion takes place only after the right side expression has been evaluated. One alternative will be to coerce all operands in the right side to the type of the target before evaluation as in the above example.

In Pascal, integer variables can be assigned to real variables, but real variables cannot be assigned to integers

In Java and C#, only widening assignment coercions are done. i.e. int value can be assigned to float variable, but not vice versa. This increases the reliability.

In Ada, there is no assignment coercion
Share with your friends: 