Let's consider the first code snippet
1) i = 7; j = 8; k = 9;
printf("%d ",(i = j) || (j = k));
printf("%d %d %d\n", i, j, k);
In the first call of printf
printf("%d ",(i = j) || (j = k));
there is used an expression with the logical OR operator.
From the C Standard (6.5.14 Logical OR operator)
3 The || operator shall yield 1 if either of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
4 Unlike the bitwise | operator, the || operator guarantees
left-to-right evaluation; if the second operand is evaluated, there is
a sequence point between the evaluations of the first and second
operands. If the first operand compares unequal to 0, the second
operand is not evaluated.
As the left operand (i = j)
of the expression is unequal to 0
then the right operand (j = k)
is not evaluated.
So after the assignment (i = j)
i
becomes equal to j
that is to 8
. The result of the expression according to the quote from the C Standard is equal to 1
.
So the first call of printf
outputs the result of the expression with the logical OR operator that is equal to 1
and the next call of printf
outputs variable i
, j
, k
that are equal to 8
, 8
, 9
.
Now let's consider the second code snippet
2) i = 1; j = 1; k = 1;
printf("%d ", ++i || ++j && ++k);
printf("%d %d %d\n", i, j, k);
In the first call of printf
there is also used an expression with the logical OR and also with logical AND operators. The first call of printf
can be rewritten like
printf("%d ", ( ++i ) || ( ++j && ++k ));
Again as the operand ++i
of the logical OR operator is not equal to 0
(its value after incrementing i
is equal to 2
) then the right operand of the logical OR operator ( ++j && ++k )
is not evaluated and the calls of printf
output correspondingly 1
, 2
, 1
, 1
.
It is interesting to consider the first call or printf
if to exchange operands of the logical OR operator the following way
printf("%d ", ++j && ++k || ++i );
The used expression is equivalent to
printf("%d ", ( ++j && ++k ) || ( ++i ) );
The first operand of the expression with the logical OR operator is an expression with the logical AND operator.
According to the C Standard (6.5.13 Logical AND operator)
3 The && operator shall yield 1 if both of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
4 Unlike the bitwise binary & operator, the && operator guarantees
left-to-right evaluation; if the second operand is evaluated, there is
a sequence point between the evaluations of the first and second
operands. If the first operand compares equal to 0, the second
operand is not evaluated.
In this case as the first operand ++j
of the logical AND operator is not equal to 0
(the value of the expression equal to 2
after incrementing j
) then the second operand ++k
will be also evaluated and its value also is not equal to 0
(it is equal to 2
after incrementing k
). So as the left operand ( ++j && ++k )
at this time of the logical OR operator is not equal to 0
then the right operand ++i
will not be evaluated and as result the output will be 1, 1, 2, 2
.
As a side note consider also the following code snippets
int i = 1;
printf( "%d\n", i++ || i++ || i++ );
printf( "%d\n", i );
The first call of printf
will output 1
while the second call of printf
will output 2
.
And
int i = 1;
printf( "%d\n", i++ && i++ && i++ );
printf( "%d\n", i );
In this case the first call of printf
also will output 1
(the result of the logical OR and of the logical AND operators is either 1
or 0
according to the provided quotes from the C Standard). And the second call or printf
will output 4
because all operands of the expression with the logical AND operator will be evaluated.