How x?y:a?b:c will be evaluated? - c

Associativity of conditional operator is from right to left so the right most conditional operator should be solved(testing whether a is true or not) first but the book mentions that first x will be tested

The fact that the conditional operator associates to the right means that x?y:a?b:c will be parsed as if it had been written x?y:(a?b:c). If it associated to the left, it would have been parsed as (x?y:a)?b:c, which would almost certainly have been a surprise (unless you are used to PHP).
But neither of these parentheses change execution order. The conditional operator's first operand is always evaluated first.

The expression
int result = x?y:a?b:c;
can be written as
int result;
if (x)
{
result = y;
}
else
{
if (a)
{
result = b;
}
else
{
result = c;
}
}
So x must be evaluated first to determine whether the if block or the else block will be executed.
Note that the ternary operator only evaluates the expression that it needs to. When x is true, y is evaluated. When x is false, the subexpression a?b:c is evaluated.
In fact, the C standard requires that the code only evaluate the expression that's needed. Here's what it says in section 6.5.15/p4:
The first operand is evaluated; there is a sequence point between its
evaluation and the evaluation of the second or third operand
(whichever is evaluated). The second operand is evaluated only if the
first compares unequal to 0; the third operand is evaluated only if
the first compares equal to 0; the result is the value of the second
or third operand (whichever is evaluated), converted to the type
described below.
In the expression x?y:a?b:c,
the first operand is x
the second operand is y
the third operand is a?b:c
So the standard expressly forbids the code from evaluating any part of a?b:c unless x compares equal to 0.
The associativity only determines how the operands are interpreted. The first, second, and third operands listed above are based on right-to-left associativity.
If the associativity of the ternary operator was left-to-right, then
the first operand would be x?y:a
the second operand would be b
the third operand would be c

Related

Is the result of the conditional operator an lvalue or rvalue?

We know that the conditional operator returns an lvalue if its Expr2 and Expr3 are lvalues of the same type otherwise it returns an rvalue:
int main(){
int a = 0, b = 0;
(a == 1 ? a : b) = 1; // C++ OK. C: error. lvalue needed
return 0;
}
The code above compiles fines on C++ while it fails to compile on C.
Here is the output on C:
main.c: In function ‘main’:
main.c:8:20: error: lvalue required as left operand of assignment
(a == 1 ? a : b) = 1;
^
In C, the result1 of the conditional operator is an rvalue (a “value” in the terminology of the C standard) because C 2018 6.3.2.1 2 says:
Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue);…
Thus, while the result of the conditional operator is its second or third operand, that operand has been converted to a value and is no longer an lvalue.
As M.M notes, you can get the same effect as selecting an lvalue by selecting addresses of operands instead and then applying *:
*(a == 1 ? &a : &b) = 1;
Footnote
1 The result of the conditional operator is not a return value, as there is no function call involved, so there is no call-and-return, just an expression evaluation.
In this C11 Draft Standard, there is a footnote that makes it clear that the result of a conditional operator is not an lvalue:
6.5.15 Conditional operator
…
Semantics
4    The first operand is evaluated; there is a sequence point between its evaluation and the evaluation of
the second or third operand (whichever is evaluated). The second
operand is evaluated only if the first compares unequal to 0; the
third operand is evaluated only if the first compares equal to 0; the
result is the value of the second or third operand (whichever is
evaluated), converted to the type described below.110)
110) A conditional expression does not yield an lvalue.
Furthermore, in this later draft Standard (dated March, 2019), the wording hasn't changed significantly (except that the footnote is therein numbered 116, rather than 110).
This is one of those cases where C++ and C differ. In C the conditional operator results in an rvalue and therefore it cannot be the left side of an assignment.
expression1? expression2 : expression3
If expression 1 has a true (non-zero) value, then the entire conditional expression takes the same value as expression 2 . If expression 1 has a false (null) value, then the entire conditional expression gets the same value as expression 3.
P r i m e r s
(5 > 3) ? 1 : 2 gets the value 1.
(3 > 5) ? 1 ; 2 gets the value 2.
(a > b) ? a : b gets a larger value among a or b.
The conditional operation itself is not a function that
returns a value.

C language and operators [duplicate]

This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 1 year ago.
#include <stdio.h>
int main()
{
int i=2;
if(i==3,4)
{
printf("If block");
}
else
{
printf("Else block");
}
return 0;
}
Why is this code returning "If block" ?``
The expression in the if statement:
(i==3,4)
Contains the comma operator. It evaluates its left operand, discards its value, then evaluated the right operand which is its result. This operator also has lower precedence than the equality operator ==, so this parses as:
((i==3),4)
So i==3 is first evaluated. Since i has the value 2 the comparison is false resulting in i==3 evaluating to 0. This value is discarded. Then 4 is evaluated which becomes the value of the entire expression. Since this value is non-zero, the if block is true, so "If block" is printed.
In the condition of the if statement
if(i==3,4)
there is used the comma operator.
From the C Standard (6.5.17 Comma operator)
2 The left operand of a comma operator is evaluated as a void
expression; there is a sequence point between its evaluation and that
of the right operand. Then the right operand is evaluated; the result
has its type and value
That is the above if statement can be equivalently written like
if( ( i==3 ), ( 4 ))
So according to the quote from the C Standard the left operand ( i == 3 ) is evaluated as a void expression that is its result is discarded. And the result of the whole expression is the value of the right operand that is of the expression ( 4 ). As this expression is not equal to 0 then the whole condition is evaluated as logical true and the sub-statement of the if statement is executed.
"Why is this code returning "If block" ?``"
The explanation of why the expression if(i==3,4) causes execution flow to go to the true branch is provided in good detail in the other answers. In short the idea that it evaluates its first operand and discards the result, Then uses the second operand to evaluate as the condition.
But, some might ask is this useful?
One use is to force a side effect prior to deciding which branch to flow to.
For example
if (numeric_read(str, &err), !err)
// ^ ^ result 'err' of side effect used in if evaluation.
^
// causes side effect by call function which assigns value to err.
(credit, in comments.)
The side effect here populates err, then discards the logical result of the call in the first argument. The value assigned to err is then used to select the branch.

C Operators and Precedence

I'm using C language, for the below code:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int num1=0;
int res = ++num1 && num1++;
printf("%d\t%d\n",num1,res);
}
In the above code I get output as 2 1. I think the output should be 2 0.
Please correct me if wrong, to solve this statement, the num1++(0) would be executed first due to highest precedence and then ++num1(2) would be executed and then at last && will be preformed because it has the lowest precedence.
Please comment how is this statement getting executed.
In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence, but if that is true then according to the associativity rule again num1++ should be executed first(right to left) which should again lead to answer as 2 0.
In the expression used as an initializer
int res = ++num1 && num1++;
there is a sequence point for the operator &&.
From 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.
and
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.
At first the left operand of the operator is evaluated and as a result num1 will be equal to 1 due to the unary (prefix) increment operator. As the sub-expression is not equal to 0 then the second operand is evaluated. Its value is the value before incrementing that is 1. As this second operand is also unequal to 0 then the whole expression is evaluated to the logical true and its value is 1 (see the first quote from the C Standard).
This value 1 is assigned to the variable res while the variable num1 after the postfix increment will be equal to 2.
So you will have that after this declaration res is equal to 1 and num1 is equal to 2.
Lots of misconceptions here. First of all, operator precedence states the order of parsing, not the order of execution. There are two related but different terms, operator precedence and order of evaluation.
See What is the difference between operator precedence and order of evaluation?.
Once you understand order of evaluation, the && operator specifically comes with well-defined sequencing, which isn't normally the case for C operators. It guarantees a left-to-right order of evaluation. C17 6.5.14/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.
Normally, you wouldn't be able to wild and crazy things with the ++ operator mixed with other operators, but the above && rule makes it possible in this specific case.
See Why can't we mix increment operators like i++ with other operators? It explains sequencing/sequence points.
In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence,
They don't, prefix ++ takes precedence over postfix (and other unary operators). So associativity does not apply.
Please correct me if wrong, to solve this statement, the num1++(0) would be executed first due to highest precedence and then ++num1(2) would be executed and then at last && will be preformed because it has the lowest precedence.
Precedence only controls which operators are grouped with which operands - it does not affect the order in which expressions are evaluated.
The &&, ||, ?:, and comma operator all force left-to-right evaluation - the left operand is fully evaluated (and any side effects applied) before the right operand. && and || both short circuit - for &&, the right operand will be evaluated only if the left operand is non-zero.
The unary (prefix) ++ operator yields the current value of the operand plus 1, so the result of ++num1 is 1. As a side effect the value in num1 is incremented. Since this result is non-zero, num1++ is also evaluated. The postfix ++ operator yields the current value of the operand, so the result of num1++ is 1. As a side effect the value in num1 is incremented.
The result of an && expression is 1 if both operands are non-zero, 0 otherwise.
It's roughly equivalent to writing
tmp = num1 + 1;
num1 = num1 + 1;
res = 0;
if ( tmp != 0 )
{
if ( num1 != 0 )
{
res = 1;
}
}
num1 = num1 + 1;
So the result of ++num1 && num1++ is 1, and the value stored in num1 at the end of it is 2.
In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence,
That is very wrong and you should stop using those tutorials immediately. Postfix operators have higher precedence than unary operators - *a++ is parsed as *(a++), ++a[i] is parsed as ++(a[i]), etc. An expression like ++i++ would be parsed as ++(i++), but you can't write such an expression in C - the result of i++ isn't an lvalue and cannot be the operand of a unary ++ like that.

Precedence of 'or' and 'and' operators in C

In the following code, I am getting 10 | 1 | 1 as a result. But according to precedence rules shouldn't 'and' operator must be evaluated first?(and yield c=9) Like : d = a || (--b)&&(--c) since 'and' has higher precedence. ( or shortcutting breaks precedence rules ?)Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
int main(){
int a,b,c,d;
a =1;
b = c = 10;
d = a|| --b&&--c;
printf("%d\n",c);
printf("%d\n",a);
printf("%d\n",d);
return 0;
}
Precedence and order of evaluation are two different things. From Logical OR
documentation (emphasis mine):
There is a sequence point after the evaluation of lhs. If the result of lhs compares unequal to zero, then rhs is not evaluated at all (so-called short-circuit evaluation).
In case of exp1 || exp2, exp1 is always evaluated first as there is a sequence point after it and if exp1 is non-zero then exp2 is not evaluated.
Precedence only determines which operands are grouped with which operators - it does not control the order in which expressions are evaluated.
In your example, it means the expression is parsed as
a || (––b && ––c)
Both || and && force left-to-right evaluation1. Both introduce a sequence point (IOW, the left hand operand will be evaluated and all side effects will be applied before the right hand operand is evaluated).
Both operators short-circuit - if the left operand of || evaluates to non-zero, then the result of the expression is 1 (true) regardless of the value of the right operand, so the right operand isn’t evaluated at all. If the left operand of && is 0, then the result of the expression is 0 (false) regardless of the value of the right operand, so the right operand isn’t evaluated at all.
In your expression, a is evaluated first. It has a non-zero value (1), so ––b && ––c is not evaluated.
Along with the ?: and comma operators. All other operators (arithmetic, equality, subscript, etc.) do not force a particular order of evaluation.

order of evaluation of comparison operator?

I have learnt that logical operator are guaranteed that their evaluation are from left-to right but I was wondering what are the order of evaluation of comparison operator. For instance expression1 < expression2 in other words is it guaranteed that expression1 will be first evaluated before expression2.
According to the standard:
J.1 Unspecified behavior
The following are unspecified:....
— The order in which subexpressions are evaluated and the order in which side effects
take place, except as specified for the function-call (), &&, ||, ?:, and comma
operators (6.5).
Generally speaking, the order of evaluation of subexpressions within an expression is undefined.
The only place where there is an order, i.e. sequence points, is the || (logical OR), && (logical AND), , (comma), and ?: (ternary) operators.
In the case of &&, if the expression on the left evaluates to false (i.e. 0), the result is known to be false and the right side is not evaluated. Similarly for || if the expression on the left evaluates to true (i.e. not 0), the result is known to be true and the right side is not evaluated.
For the ternary operator, the conditional is evaluated first. If it evaluates to true then only the middle part is evaluated, otherwise only the third part is evaluated.
For the comma operator, the left side is evaluated first, then the right side.
From the C standard:
6.5.13.4 Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation; there is a sequence point
after the evaluation of the first operand. If the first
operand compares equal to 0, the second operand is not evaluated.
...
6.5.14.4 Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; there is a sequence point after the
evaluation of the first operand. If the first operand
compares unequal to 0, the second operand is not evaluated.
...
6.5.15.4 The first operand is evaluated; there is a sequence point after its evaluation. The second operand is evaluated only if the
first compares unequal to 0; the third operand is evaluated only if
the first compares equal to 0; the result is the value of the second
or third operand (whichever is evaluated), converted to the type
described below. If an attempt is made to modify the result of a
conditional operator or to access it after the next sequence point,
the behavior is undefined.
....
6.5.17.2 The left operand of a comma operator is evaluated as a void expression; there is a sequence point after its
evaluation. Then the right operand is evaluated; the result has its
type and value. If an attempt is made to modify the result of a comma
operator or to access it after the next sequence point, the behavior
is undefined.
No, the spec does not mention the order of evaluation for the operand of relational operators. It's unspecified.
Just to add, relational operators are left-to-right associative.

Resources