PowerPoint Presentation
CSE 2421
The C Language – Part 1.2
Required Reading:
Computer Systems: A Programmer’s Perspective, 3rd Edition,
Chapter 1 thru Section 1.3
Pointers on C,
Chapter 5 thru Section 5.1.3, 5.3 through the end of the chapter
lvalue/Lvalue/L-value: That operand found on the left side of the assignment operator.
All L-values must be modifiable since they are being assigned a value.
rvalue/Rvalue/R-value: That expression found on the right side of the assignment operator.
R-values can be constants, expressions, be a return value from a function, etc.
Terminology
Operators
C operators can be classified according to the number of operands which they take.
C has unary operators, binary operators, and one ternary operator (the conditional operator ? : )
The operands of C operators are expressions, which can be constants, variables, or expressions which contain one or more operators.
Expressions will always be evaluated by the code which the compiler generates; that is, an expression has a value (which has a type, of course).
There is a table of operators posted on Carmen which shows which operators are unary, binary or ternary, and the precedence and associativity of each operator (precedence/associativity covered below).
4
Operators – continued
Precedence refers to the relationship between two operators in terms of the order in which the operations are performed.
Precedence is a binary relation, that is, it is defined with respect to pairs of (adjacent) operators. Binary operators are adjacent if they have one operand in common; unary operators are adjacent if they have the same operand.
We can always enforce a precedence different from the precedence specified by the language for 2 operators by using parentheses, because operations inside parentheses are done first (Have the highest precedence).
If two adjacent operators have the same precedence, then associativity is relevant.
L-R associativity means that the operation specified by the leftmost operator is done first, and then the one specified by the rightmost operator. R-L associativity, of course, means the opposite order.
Precedence and Associativity
#include
/* program to show associativity of the “/” operator */
int main() {
float num1;
float num2;
float num3;
num1 = 2.0 / 1.0 / 2.0;
num2 = (2.0 / 1.0) / 2.0;
num3 = 2.0 / (1.0 / 2.0);
printf(“num1 is: %f \n”, num1);
printf(“num2 is: %f \n”, num2);
printf(“num3 is: %f \n”, num3);
}
What is printed?
6
Associativity
#include
/* program to show associativity of the “/” operator */
int main() {
float num1;
float num2;
float num3;
num1 = 2.0 / 1.0 / 2.0;
num2 = (2.0 / 1.0) / 2.0;
num3 = 2.0 / (1.0 / 2.0);
printf(“num1 is: %f \n”, num1); /* num1 is: 1.000000 */
printf(“num2 is: %f \n”, num2);
printf(“num3 is: %f \n”, num3);
}
7
Associativity
#include
/* program to show associativity of the “/” operator */
int main() {
float num1;
float num2;
float num3;
num1 = 2.0 / 1.0 / 2.0;
num2 = (2.0 / 1.0) / 2.0;
num3 = 2.0 / (1.0 / 2.0);
printf(“num1 is: %f \n”, num1); /* num1 is: 1.000000 */
printf(“num2 is: %f \n”, num2); /* num2 is: 1.000000
Result with L-R associativity */
printf(“num3 is: %f \n”, num3);
}
8
Associativity
#include
/* program to show associativity of the “/” operator */
int main() {
float num1;
float num2;
float num3;
num1 = 2.0 / 1.0 / 2.0;
num2 = (2.0 / 1.0) / 2.0;
num3 = 2.0 / (1.0 / 2.0);
printf(“num1 is: %f \n”, num1); /* num1 is: 1.000000 */
printf(“num2 is: %f \n”, num2); /* num2 is: 1.000000
Result with L-R associativity */
printf(“num3 is: %f \n”, num3); /* num3 is: 4.000000
Result with R-L associativity */
}
9
Associativity
Let’s see how an expression is evaluated, using the precedence and associativity in C.
Suppose, before this statement is executed,
a = 1, b = 3, and c = 5:
d = ++a * c + b++;
How does the compiler determine the order of operations?
Example for Precedence
How does the compiler determine the order of operations?
We can take the view that the compiler does the binary operation with the highest precedence first, then next highest, but expressions with unary operators are not evaluated until they need to be, in order to evaluate a larger expression of which they are a part.
We will also suppose that operands of binary operators are evaluated left to right (this is true for most compilers, and it is true for ours).
A good practice is to use parentheses to show the order of evaluation, starting with the binary operator which has the highest precedence, and going to the lowest, considering associativity where necessary.
So, let’s try to parenthesize the binary operators in the expression above, after parenthesizing all unary operator expressions (unary operators have higher precedence than all binary operators generally).
Example for Precedence
Parenthesize unary operators:
d = (++a) * c + (b++);
Precedence of binary operators: * first, then +, then =
Now we can add the rest of the parentheses:
d = (((++a) * c) + (b++));
What is d after execution of this statement (Remember, before this statement, a = 1, b = 3, and c = 5)?
Example for Precedence
Value of expression
2 5 3
(d = (((++a) * c) + (b++)));
d = (2 * 5) + 3
So, d has the value 13 after the statement is executed (a = 2, b = 4, and c = 5)
Example for Precedence (continued)
void main()
{
int a, b, c, d;
a=1;
b=3;
c=5;
d = ++a * c + b++;
printf(“d = %d, when no parens are used.\n”, d);
printf(“a=%d, b=%d, c=%d\n”, a, b, c);
a=1;
b=3;
c=5;
d = (++a) * c + (b++);
printf(“d = %d, when some parens are used.\n”, d);
printf(“a=%d, b=%d, c=%d\n”, a, b, c);
a=1;
b=3;
c=5;
d = (((++a) * c) + (b++));
printf(“d = %d, when all parens are used.\n”, d);
printf(“a=%d, b=%d, c=%d\n”, a, b, c);
}
Does parens change b++???
[jones.5684@cse-fac2 test]$ gcc -ansi -pedantic -o precedence precedence.c
[jones.5684@cse-fac2 test]$ precedence
d = 13, when no parens are used.
a=2, b=4, c=5
d = 13, when some parens are used.
a=2, b=4, c=5
d = 13, when all parens are used.
a=2, b=4, c=5
[jones.5684@cse-fac2 test]$
In C, assignments are expressions. This means that an assignment expression, just as any expression, has a value, which is the value of the rightmost expression.
Lowest precedence (except for the comma operator)
Embedded assignments – legal anywhere an expression is legal.
This allows multiple assignment: a = b = 1; /*R-L associativity */
We’ll see how these are used in C a bit later.
Other assignment operators (compound assignment operators) – same associativity – R-L
+= , –= , *= , /= , %=
NOTE: Using an assignment operator (=) is legal anywhere it is legal to compare for equality (==), so it is not a syntax error (some compilers may give a warning, although our compiler will not!!!).
Assignment Operator
In Spring 1993, in the Operating System development group at SunSoft, we had a “priority-one” bug report come in describing a problem in the asynchronous I/O library. The bug was holding up the sale of $20 million worth of hardware to a customer who specifically needed the library functionality, so we were extremely motivated to find it. After some intensive debugging sessions, the problem was finally traced to a statement that read:
x==2;
It was a typo for what was intended to be an assignment statement. The programmer’s finger had bounced on the “equals’ key, accidentally pressing it twice instead of once. The statement as written compared x to 2, generated true or false, and discarded the result.
C is enough of an expression language that the compiler did not complain about a statement which evaluated an expression, had no side-effects, and simply threw away the result. We didn’t know whether to bless our good fortune at locating the problem, or cry with frustration at such a common typing error causing such an expensive problem
The $20 Million Bug
Expert C Programming:Deep C Secrets, Peter Van Der Linden
Mathematical Symbols
+ – * / %
addition, subtraction, multiplication, division, modulus
Works for both integers and float
+ – * /
/ operator performs integer division if both operands are integer, i.e., truncates; otherwise, if at least one operand is float, performs floating point division (i.e., casting is used – more on this later).
% operator divides two integer operands and gives integer result of the remainder
Associativity – L-R.
Precedence:
1. Anything inside ()
2. * / %
3. + –
Arithmetic Operators
++a and a++ have the behavior of a = a + 1
–a and a– have the behavior of a = a – 1
[Postfix operators have higher precedence than prefix operators]
HOWEVER…
++a a is incremented BEFORE a is evaluated in the expression
–a a is decremented BEFORE a is evaluated in the expression
a++ a is incremented AFTER a is evaluated in the expression
a– a is decremented AFTER a is evaluated in the expression
In both examples below, the final value of a is 2
++a– compiler will accept, but behavior is undefined/inexact
(pick a compiler and roll the dice.)
Unary Operators
int main()
{
int a = 1;
printf (“ a is %d”, a++);
return 0;
}
/* 1 will be printed */
int main()
{
int a = 1;
printf (“ a is %d”, ++a);
return 0;
}
/* 2 will be printed */
/docProps/thumbnail.jpeg