Reference: Kelley & Pohl, Chapter 4 (4.17)
· Consider the following statement that sets z to the max of a and b:

if (a > b)
z = a;
else
z = b;

· The conditional expression operator may be used instead.
· The ternary operator ?: may be used thus:
expr1 ? expr2 : expr3
· Thus, our example may be rewritten:

· The right hand side is an expression which has the value of max(a,b). In fact, the ternary expression is often used in macros, e.g.,
· #define MAX(A,B) (((A) > (B)) ? (A) : (B))
· Also, because ?: is an expression, if expr2 or expr3 are of different types, the result is an expression of the highest type. This activity is often called “type promotion.”
· That is, in the code fragment:

Double d = 10.23;
Float f = 3.1416;
int i = 10;
...
x = (d > 0) ? f : i;

the resulting type of the righthand side of the assignment to x is float because a mixed expression with float and int becomes float (expr2 is float, expr3 is int).
· The precedence of ?: is just above the assignment operators.
· It associates right to left.
The conditional operator
Recall that the conditional operator ?: has the following syntax:
conditional_expression

::=

expr1 ? expr2 : expr3

expr1

::=

expression

expr2

::=

expression

expr3

::=

expression

· Also, recall that this operator has the semantics that expr1 is evaluated first.
· Then if expr1 is nonzero (true), expr2 is evaluated and that is the value of the conditional expression as a whole.
· Otherwise, expr1 is zero (false), and expr3 is evaluated making it the value of the conditional expression as a whole.
· Consequently, the conditional operator can be used to perform the work of an ifelse statement.
· Note that this can quickly get out of hand if you’re not careful…
example
ifelse construct

equivalent conditional

if (y < z)
x = y;
else
x = z;

x = (y < z)
? y
: z;

if (a > 0)
z = 1;
else if (a < 0)
z = 1;
else
z = 0;

z = (a > 0)
? 1
: ((a < 0) ? 1 : 0);

if (a > b)
if (a > c)
z = a;
else
z = c;
else if (b > c)
z = b;
else
z = c;

z = (a > b)
? ((a > c) ? a : c)
: ((b > c) ? b : c);

The conditional operator  example
· In the following example, assume that the following declarations are in scope:
char a = 'a'; /* a has an ASCII value of 97 */
char b = 'b'; /* b has an ASCII value of 98 */
int i = 1;
int j = 2;
double x = 7.07;

· Then, the following table illustrates the effect of the conditional operator.
· Exercise: explain why the first expression is an int rather than char
Expression

Equivalent Expr

Value

Type

i==j ? a1 : b+1

(i==j) ? (a1) : (b+1)

99

int

j%3==0 ? i+4 : x

((j%3)==0) ? (i+4) : x

7.07

double

j%3 ? i+4 : x

(j%3) != 0 ? (i+4) : x

5.0

double

Comma operator
· When used within an expression, the comma ',' operator, or sequencing operator, is defined thus:
"A pair of expressions separated by a comma is evaluated left to right, and the type and value of the result are the type and value of the right operand."
· The comma operator has the lowest possible precedence (lower than assignment statements).
· The comma operator associates from left to right.
f (a (), (b (), c ()));
/* call f with two parameters */
· A better way to do this might be the following:
b ();
f (a (), c ());
note
· The commas that separate function arguments, variables in declarations, etc., are not comma operators, and do not guarantee left to right evaluation.
example
· The statement

is exactly equivalent to writing

· Comma operators are commonly used within for loops to initialize more than one looping index, e.g.:

for (i = 0, j = 1, k = 2;
i < n;
i++, j++, k++) {
...
}

Precedence and order of evaluation
Operator

Associativity

Order of Evaluation

()

left to right



! ++ 
(unary) + 
(indirection) *
& ( type ) sizeof

right to left



* / %

left to right



+ 

left to right



< <= >= >

left to right



== !=

left to right



&&

left to right

left to right
sequence point after first argument
short circuit



left to right

left to right
sequence point after first argument
short circuit

?:

right to left

first operand eval
sequence point after first argument

=
+= =
*= /= %=

right to left



,

left to right

left to right
sequence point after first argument

ANSI notes on the comma and other operators in C
· The ANSI draft, page 55, states the following about the comma operator:
"The left operand of a comma operator is evaluated as a void expression; there is a sequence point after its evaluation."
· It is also important to note that the comma operator yields an expression and does not yield an lvalue. Thus, the following is incorrect:
int k;
int j;
(j = 10, k = 20) = 40;
· In other places it states that as && and  guarantee left to right evaluation, there is also a sequence point after evaluating the first operand.
· In general, a semicolon ';' denotes a sequence point, i.e. it is the point at which everything must synch up.
· Up until that point, all subexpressions can be conceptually evaluated in parallel.
Precedence, associativity, and order of evaluation
· Precedence, associativity, and order of evaluation are orthogonal concepts, e.g.,
10 * 20 + 20 / 5 + 15 … ((10 * 20) + (20 / 5)) + 15
· Most operators do not have an order of evaluation specified
· This “underspecification” allows compilers to optimize your code
· Only logical and '&&', logical or '', the ternary operator '?:', and the comma ',' operator explicitly specify order of evaluation and define sequence points
· Also, note that the ternary operator associates right to left.
Order of evaluation  pitfalls
· With the exception of &&, , ?:, and the comma operator, C does not specify the order in which operands of an operator are evaluated.
example
· The code fragment

may evaluate f() followed by g(), or it may choose to evaluate g() followed by f().
· Adding parentheses changes nothing, e.g.:
x = (f ()) + g ();
· The only way to guarantee order of evaluation is to split this up into several statements
x1 = f ();
x2 = g ();
x = x1 + x2;
Order of evaluation  pitfalls (2)
· Similarly, the order in which arguments to a function are evaluated is not specified.
printf ("%d %d\n", ++n, power (2, n)); /* wrong */

· Different results will occur depending on whether ++n is evaluated before or after power(2,n) is evaluated.
· Changing the ++n to n++ can still lead to unpredictable results
· The underlying problem is that we have a potential “race condition”
· Other types of race conditions occur in concurrent programs
The while statement
Reference: Brooks, Chapter 4 (4.4)

The syntax of a while statement is as follows.
while_statement

::=

While (expression) statement


Generally, statement is a compound statement
The while statement (2)
Some examples are
int x = 0;
int i = 0;
while (i < n)
{
x = x + i; /* x++ */
i = i + 1; /* i++ */
}

int c;
while ((c = getchar ()) != EOF) {
/* Only works for ASCII,
better to use islower (c). */
if (c >= 'a' && c <= 'z')
++lowercase_letter_cnt;
++total_cnt;
}

but not
while (++i < LIMIT) do {
/* syntax error: do is not allowed */
j = 2 * i + 3;
printf ("%d\n", j);
}

· In general, given a sequence of statements of the form

while (expression)
statement
next statement

the first expression is evaluated.
· If it is nonzero (true), then statement is executed repeatedly until expression becomes zero (false).
· When expression becomes false, control is passed to next statement.
Example  computing factorials
#include
int main (void)
{
int i, n;
double factorial;
printf ("Enter a positive integer: ");
scanf ("%d", &n);
factorial = 1.0;
i = 1;
while (i <= n)
{
factorial = factorial * i;
// factorial *= i;
i = i + 1;
// i++;
}
printf ("%d factorial = %.2f\n", n, factorial);
return 0;
}


Whenever you write a while loop, be sure you determine how it will terminate

A common error would be to omit the increment of i

The result would be an endless loop

Another common error is to forget to initialize i before the beginning of the loop

In this case, the behavior is unpredicatable
Example  computing factorials (2)
The main code fragment
factorial = 1.0;
i = 1;
while (i <= n)
{
factorial = factorial * i;
i = i + 1 ;
}
may be rewritten more concisely as follows
factorial = 1.0;
i = 1;
while (i <= n)
factorial *= i++;
but not as follows
factorial = 1;
i = 1;
while (i < n)
factorial *= i;
The last example is an infinite loop. The looping variable i is never modified and thus never becomes >= n
Example  Fibonacci Numbers

The Fibonacci sequence is a sequence of numbers where the current number is the sum of the previous two numbers in the sequence

The first two numbers in the sequence is 1

The next number is 1 + 1 = 2

The next number after that is 1 + 2 = 3

Here are the first 10 numbers of the sequence:
1 1 2 3 5 8 13 21 34 55

Now we write code to generate N Fibonacci numbers and compute their sum
prev1 = prev2 = 1; /* first two numbers */
sum = 2; /* sum of the first two numbers */
count = 2; /* calculate 3rd number on */
while (count < N)
{
int curr = prev1 + prev2;
sum += curr;
prev1 = prev2; /* advance prev1 */
prev2 = curr; /* advance prev2 */
count++;
}

If N=10, how many iterations does this loop execute? What is the final value of count when N=10?

If N=5, what are the final values of curr, sum, prev1, and prev2?
example  binary search
/* binsearch: find x in v[0] <= ... <= v[n1]
 return index of x in a sorted array of numbers
*/
int binsearch (int x, int v[], int n)
{
int low = 0;
int high = n  1;
while (low <= high) {
int mid = (low + high) / 2;
if (x < v[mid]) /* smaller */
high = mid  1;
else if (x > v[mid]) /* larger */
low = mid + 1;
else /* we found it */
return mid; /* return the index */
}
return 1; /*NOT FOUND*/
}

exercise
Identify the statements within each if or while construct.
Example @@
· Because C allows side effects within expressions, some or possibly all of the work may be performed as part of the test.
· The following example illustrates a case where all of the work is done during the test.
#include
#include
int skip_spaces (void)
{
int c;
while ((c = getchar ()) != EOF && isspace (c))
/* null */;
return c;
}

· The while loop read characters one at a time and stops either when it hits endoffile or when the character is no longer a whitespace character.
· The null statement ; is the body of the loop.
The FOR statement (1)

The syntax of a for statement is as follows.
for ( initializationexpression ;
condition ;
nextexpression )
statement
next statement
Example  computing factorials
factorial = 1;
i = 1;
while (i <= n)
{
factorial *= i;
i++;
}

factorial = 1;
for (i = 1; i <= n; i++)
{
factorial *= i;
}

Share with your friends: 