CS210
Answer 3 9/12/01

OUTPUT:
1     (Operators 3.1)
1     (Operators 3.2)
2     (Operators 3.3)
0    
3     (Operators 3.4)
0    
?     (Operators 3.5)

Derivation

Operators 3.1

initially x=2, y=1, z=0  
x = x ∓∓ y || z  
x = (x∓∓y) || z Bind operators to operators according to precedence.
x = ((x∓∓y)||z)  
(x=((x∓∓y)||z))  
(x=((TRUE∓∓TRUE)||z)) Logical operators are evaluated from left to right. An operand to a logical operator is FALSE if it is zero and TRUE if it is anything else.
(x=(TRUE||z)) The logical AND, &&, yields TRUE only when both its operands are TRUE, otherwise FALSE.
(x=(TRUE||whatever)) Once one argument to the OR, ||, is known to be TRUE we know the result of the || will be TRUE regardless of the other operand. Hence there is no need to evaluate the expression further.
(x=TRUE)  
(x=1)  
1  

More about define. The define statement that begins this program is a little fancier than that in the previous program. Here, PRINT is the name of a macro with arguments, not just a simple string. The preprocessor performs two levels of substitution on macros with arguments: first the actual arguments are substituted for the formal arguments in the macro body, and then the resulting macro body is substituted for the macro call.

For example, in this program PRINT has one formal argument, int. PRINT(x) is a call of PRINT with the actual argument x. Thus, each occurrence of int in the macro body is first replaced by x, and then the resulting string, printf("%d\n",x), is substituted for the call, PRINT(x). Notice that the formal parameter int did not match the middle letters in printf. This is because the formal arguments of a macro are identifiers; int only matches the indentifier int.

Operators 3.2

Initially x=1, y=1, z=0  
x || ! y && z  
x || (!y) && z Binding operands to operators
x || ((!y)&&z)  
(x||((!y)&&z))  
(TRUE||((!y)&&z)) Evaluating from left to right
(TRUE||whatever)  
TRUE, or 1  


Operators 3.3

Initially x=1, y=1  
z = x ++ - 1  
z = (x++) - 1 Following precedence.
z = ((x++)-1) Following precedence.
(z=((x++)-1))  
(z=(1-1)), and x=2 The ++ to the right of its operand is a post increment. This means that x is incremented after its value is used in the expression.
(z=0)  
0  


Operators 3.4

Initially x=2, y=1, z=0  
z += - x ++ + ++ y  
z += - (x++) + (++y) Unary operators associate from right to left, thus ++ binds before unary -. (Actually, the expression would not be legal if it were arranged so that the - bound first since ++ and -- expet a reference to a variable (an lvalue) as their operand. x is an lvalue, but -x is not.)
z += (-(x++)) + (++y)  
z += ((-(x++))+(++y))  
(z+=((-(x++))+(++y)))  
(z+=((-2)+2)), and x=3, y=2 Evaluating from inside out.
(z+=0)  
(z=0+0)  
(z=0)  
0  


Operators 3.5

Initially x=3, z=0  
z = x / ++ x  
z = x /(++x)  
z =(x/(++x))  
(z=(x/(++x)))  
  You may be tempted at this point to begin evaluating this expression as before, from the inside out. First the value of x would be retrieved and incremented to be divided into the value of x. One question that might be asked is what value is retrieved from x for the numerator, 3 or 4? That is, is the value for the numberator retrieved before or after the increment is stored? The C language does not specify when such a side effect* actually occurs; that is left to the compiler writer. The message is to avoid writing expressions that depend upon knowing when a side effect will occur.

A side effect is any change to the state of a program that occurs as a byproduct of executing a statement. By far the most common side effects in C relate to storing intermediate values in variables, such as with the increment operator as above or with an embedded assignment operator.