Evaluation order in ternary operator with increments - c

#define MAX(a,b) ((a)>(b) ? (a) : (b))
int main(void) {
int a=2;
int b=3;
int c = MAX(a++,b++); // c=((a++)>(b++) ? (a++) : (b++));
printf("\na= %d", a);// a=3
printf("\nb= %d", b);//b=5
printf("\nc= %d", c);//c=4
a=3;
b=2;
cc = MAX(a++,b++); // c=((a++)>(b++) ? (a++) : (b++));
printf("\na= %d", a); // a=5
printf("\nb= %d", b); //b=3
printf("\nc= %d", c); //c=4
return 0;
}
I would like to know why c is not evaluating to 5.
It appears to me the evaluation order should be:
First both a and be get incremented in (a++)>(b++)
If for example the first one is greater, the ternary operator in
c=((a++)>(b++) ? (a++) : (b++)), goes to (a++), so a
increments again.
The result of the ternary expression, which is a twice-increment,
should be assigned to c, then c should have the greater value
twice-incremented, that is 5. However, I am getting 4. I suspect the
greater value's second increment is happening at the end, but I can't
explain why, since the parentheses seem to indicate that the
assignment comes at the end.
Any idea?

The postfix ++ operator has a result and a side effect. The result of a++ is the value of a before the increment - given
int a = 1;
int x = a++;
the value of x will be 1 and the value of a will be 2. Note that the side effect of adding 1 to a does not have to be applied immediately after evaluation - it only has to be applied before the next sequence point.
So, looking at
((a++) > (b++)) ? (a++) : (b++)
The ?: operator forces left-to-right evaluation, so the first thing that happens is that (a++) > (b++) is evaluated1. Since a is initially 2 and b is initially 3, the result of the expression is false (0). The ? operator introduces a sequence point, so the side effects to a and b are applied and a is now 3 and b is now 4.
Since the result of the condition expression was 0, we evaluate b++. Same thing, the result of the expression is the current value of b (4), and that value gets assigned to c. The side effect to b is applied at some point, and by the time everything's finished, a is 3, b is 5, and c is 4.
Although within that expression either a++ or b++ may be evaluated first, since the > operator doesn't force left-to-right evaluation.

Let's consider for example this declaration
int c = MAX(a++,b++);
after the macro substitution there will be
int c = (( a++) >( b++ ) ? (a++) : (b++));
The variables a and b are initialized like
int a=2;
int b=3;
As a is less than b then the third expression (b++) will be evaluated as a result of the conditional operator. In the first expression ( a++) >( b++ ) a and b were incremented. There is a sequence point after the evaluation of the first expression.
So a will be set to 3, b will be set to 4.
As it was already said the value of the conditional operator is the value of the third expression (b++) where there is used the post-increment. The value of the post-increment operator is the value of its operand before incrementing.
From the C Standard (6.5.2.4 Postfix increment and decrement operators)
2 The result of the postfix ++ operator is the value of the
operand. As a side effect, the value of the operand object is
incremented (that is, the value 1 of the appropriate type is added to
it).
So the value of the conditional operator is 4. This value will be assigned to the variable c. But as a side effect the value of b will be incremented.
Thus after this declaration a will be equal to 3, b will be equal to 5 and c will be equal to 4.
For clarity this declaration
int c = (( a++) >( b++ ) ? (a++) : (b++));
in fact can be rewritten in the logically equivalent way.
int result = a > b;
++a;
++b;
int c;
if ( result != 0 )
{
c = a++;
}
else
{
c = b++;
}

For a++ it's equivalent as saying
int temp = a;
a = a + 1;
return temp;
so in the case of a=2, b=3, we can go to the condition (a++)>(b++) and we can have a rewritten as
int temp1 = a;
a = a + 1;
return temp1;
and b rewritten as
int temp2 = b;
b = b + 1;
return temp2;
now since it's only a conditional statement, we're really just evaluating the old values of a and b before the increment which is temp1 = 2 and temp2 = 3 while at the same time a and b values have changed a = 3, b = 4. Since temp1 < temp2 from the old value, we go to the false clause of the ternary operator (b++) and do the same thing as we did before
int temp3 = b;
b = b + 1;
return temp3;
so now b is 5 while the returned temp3 is the previous value of b which is 4. Hope this helps!

Related

How exactly does the ?: operator work in C?

I have a question, how the compiler operate on the following code:
#include<stdio.h>
int main(void)
{
int b=12, c=11;
int d = (b == c++) ? (c+1) : (c-1);
printf("d = %i\n", d);
}
I am not sure why the result is ‍‍‍d = 11.
In int d = (b == c++) ? (c+1) : (c-1);:
The value of c++ is the current value of c, 11. Separately, c is incremented to 12.
b == 11 is false, since b is 12.
Since (b == c++) is false, (c-1) is used. Also, the increment of c to 12 must be completed by this point.
Since c is 12, c-1 is 11.
d is initialized to that value, 11.
According to the C Standard (6.5.15 Conditional operator)
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)
So in the initializing expression of this declaration
int d = (b == c++) ? (c+1) : (c-1);
the variable b is compared with the value of the variable c because the post-increment operator returns the value of its operand before incrementing it.
As the values are not equal each other (b is set to 12 while c is set to 11) then the sub-expression (c-1) is evaluated.
According to the quote there is a sequence point after evaluation of the condition of the operator. It means that after evaluation of the condition c has the value 12 after applying the post-increment operator to the variable c. As a result the variable d is initialized by the value 1 (12 - 1).
Translated to a regular if-statement your code would look like this:
int b=12, c=11;
int d;
if (b == c++)
d = c+1;
else
d = c-1;
The clue here is that c is incremented after the condition is checked. So you enter the else state but c already has the value 12 there.
Beacuse the condition is false, therefore the false case will happen: c-1, but since you incremented c in the condition by c++, therefore c is now 12. The result thus 12 - 1 which is 11.
EDIT:
What OP misunderstood was the post increment.
So what actually happen is like this:
#include<stdio.h>
int main(void)
{
int b=12, c=11;
int d;
if (b == c) { // 12 == 11 ? -> false
c = c + 1;
d = c + 1;
} else { // this executes since condition is false
c = c + 1; // post increment -> c++ -> c = 12 now
d = c - 1; // 12 - 1 = 11 -> d = 11
}
printf("d = %i\n", d);
}
Refer to Ternary Operator.
Syntax
condition ? value_if_true : value_if_false
So, you wrote
int d = (b == c++) ? (c+1) : (c-1);
In this situation, the result will be 11 because, after if checks, 'c' value is increased(c+1=12) and only after that it sets 'd' value as c(12)-1 which is 11.
If you used, for example:
int d = (b == ++c) ? (c+1) : (c-1);
"c" value would be increased before checking the statement, so it would be true and "d" value would be c(12)+1 which is 13.

Questions on C expression

Here is a program:
#include<stdio.h>
#include<conio.h>
main()
{
int a,b,c;
a=12;
++a;
b=a++;
c=++a;
printf("a=%d,b=%d,c=%d",a,b,c);
getch();
}
The answers are a=15,b=13, c=15. But how?
x=++y means y is incremented before x receives the value of y.
x=y++ means y is incremented after x receives the value of y.
In the code:
The first ++a makes a = 13.
The line b=a++ makes b=a (13) and after that a = 14.
The line c=++a makes a = 15 and after that c = a (15).
The expression a++ evaluates to the current value of a; as a side effect, a is incremented. Thus, the expression
b = a++;
is equivalent to
b = a;
a = a + 1;
with the caveat that the exact timing of the updates to a and b with respect to each other isn’t specified. IOW, it’s possible that the current value of a is stored in a register, then a is incremented, then the value in the register is written to b. It’s possible that a and b are updated in parallel. All that’s guaranteed is that b gets the previous value of a.
The expression ++a evaluates to the current value of a + 1, and as a side effect increments a. Thus, the expression
c = ++a;
is equivalent to
c = a + 1;
a = a + 1;
with the same caveat as above.
++a means increment a, then use (in this case save).
a++ means use then increment
++a or a++ both work as a=a+1 but ++a first increases value of a by 1 and then assigns it to a. while a++ first assigns the value of a and then increments it by 1.
initially the value of a is declared as 12
statement '++a' first increases value of a by 1 and then assigns it to a. thus now, a=13
in statement b=a++, Value of a i.e. 13 is assigned to b and then it is incremented by 1. thus now, b=13 & a=14
in statement c=++a, value of a is incremented by 1 first and then it is assigned to c. thus c=15 & a=15.

Understand comma operator

int main()
{
int a = (1,2,3);
int b = (++a, ++a, ++a);
int c= (b++, b++, b++);
printf("%d %d %d", a,b,c);
}
I am beginner in programming. I am not getting how does this program shows me output of 6 9 8.
The , used in all the three declarations
int a = (1,2,3);
int b = (++a, ++a, ++a);
int c = (b++, b++, b++);
are comma operator. It evaluates the first operand1 and discard it, then evaluates the second operand and return its value. Therefore,
int a = ((1,2), 3); // a is initialized with 3.
int b = ((++a, ++a), ++a); // b is initialized with 4+1+1 = 6.
// a is 6 by the end of the statement
int c = ((b++, b++), b++); // c is initialized with 6+1+1 = 8
// b is 9 by the end of the statement.
1 Order of evaluation is guaranteed from left to right in case of comma operator.
The code is not in any way good and nobody in their right mind would ever write it. You should not spend any time in looking at that kind of code, but I will still give an explanation.
The comma operator , means "do the left one, discard any result, do the right one and return the result. Putting the parts in parentheses doesn't have any effect on the functionality.
Written more clearly the code would be:
int a, b, c;
a = 3; // 1 and 2 have no meaning whatsoever
a++;
a++;
a++;
b = a;
b++;
b++;
c = b;
b++;
The pre- and post-increment operators have a difference in how they act and that causes the difference in values of b and c.
I am beginner in programming. I am not getting how does this program
shows me output of
Just understand comma operators and prefix ,postfix .
according to rules mentioned in links given to you
int a = (1,2,3); // a is initialized with 3 last argument .
int b = (++a, ++a, ++a); // a is incremented three time so becomes 6 and b initilized with 6 .
int c = (b++, b++, b++); // b incremented two times becomes 8 and c initialized with 8.
// b incremented once more time becomes 9

Order of evaluation for conditional operator

It is known that both assignment = and conditional ?: operators have right associativity. In following code sample:
#include <stdio.h>
int main(void)
{
int a, b, c, d;
a = b = c = d = 1;
1 ? a++ : b ? c++ : d;
printf("%d %d %d %d\n", a, b, c, d);
return 0;
}
the assignment:
a = b = c = d = 1;
is equivalent to:
a = (b = (c = (d = 1)));
and correspondingly:
1 ? a++ : b ? c++ : d;
is the same as:
1 ? a++ : (b ? c++ : d);
What the Standard say about this last case? Does it guarantee that such combined expression is evaluated from left to right (so the c++ part is not evaluated), just as opposite to assignment?
The evaluation order of ?: is guaranteed: the first operand is evaluated first, then evaluate the second or the third operand depending on whether the first operand is true.
You are mainly confused about the relationship between operator precedence/associativity and order of evaluation. They play different roles. The former decides how operators are grouped, while the latter decides which sub-expression is evaluated first.
Consider the expression a * b + c * d, the precedence rule means it's equivalent to (a * b) + (c * d). But is it guaranteed that the compiler will evaluate a * b before c * d? The answer is no, in this example, the operator + doesn't guarantee the order of evaluation.
The conditional operator ?: is one of the few operators that do have a specified order of evaluation. (The rest are &&, ||, and ,).
In your example
1 ? a++ : b ? c++ : d;
1 ? a++ : (b ? c++ : d);
are always equivalent, in both expressions, 1 is evaluated first, and since it's true, a++ is evaluated next, the end.
Associativity and precedence do not define order of evaluation. These concepts are completely unrelated. Order of evaluation in C is defined by sequencing rules, not by precedence or associativity.
It is true that a = b = c = d = 1; is associated as a = (b = (c = (d = 1)));, but that does not mean that d = 1 should be evaluated first, especially in C language, where assignment operator evaluates to an rvalue.
Associtivity simply says that c should receive value 1 converted to the type of d ("as if" it was read from d). But that does not mean that d = 1 should be done first. In your example all variables have the same type, which means that the whole thing is equivalent to a = 1; b = 1; c = 1; d = 1; in absolutely any order. There's no sequencing inside a = b = c = d = 1 expression.
The same logic applies to ?: operator. Its associativity simply tells you which operand belongs to which operator. And the grouping is indeed 1 ? a++ : (b ? c++ : d);. But associativity does not tell you anything about the order of evaluation. Order of evaluation in ?: operator is defined separately and independently: the condition is always evaluated (sequenced) first, then one (and only one) of the branches is evaluated. In your example 1 is evaluated first, then a++ is evaluated and its result becomes the result of the entire expression. The (b ? c++ : d) part is not even touched.
1 ? a++ : b ? c++ : d;
is equivalent to
if (1) {
a++;
}
else {
if (b) {
c++;
}
else {
d;
}
}
So, the output will be
2 1 1 1

increment operator within conditional operator in c

I expected b to be 3.
is this an undefined behavior?
or the result could be predicted?
but i thought b would be 3.
and c would be 2.
the output i got is 1 2 1
please explain
#include<stdio.h>
int main()
{
int a = 0;
int b = 1;
int c = (a++ >b++ )? a++ : b++;
printf("%d %d %d",a,b,c);
return 0;
}
That's what I get, and I agree it's guaranteed to be that. There is a sequence point after evaluating the first operand (the condition) before going to the second or third operand. So it goes like this:
(a++ >b++ )
evaluates to:
0 > 1
which is 0.
After that, a is 1 and b is 2.
Since it was false:
b++
is evaluated. The result is 2 (which is assigned to c), and afterwards b is 3.
If that's the exact code, your compiler is buggy. It's not even a question of order. Even if the third operand were evaluated before the first (which would be wrong), b should still be 3.
I am using GCC 4.6.3, but the result will be the same in all standards-compliant compilers.
It's defined behavior, there's a sequence point between the first operand of ?: and second or third one.
So after evaluating a++ < b++, a = 1 and b = 2. Then the third operand gets selected. Thus c gets assigned b++. So c = 2 and then b = 3.
The C11 standard says:
6.5.15 Conditional operator
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).

Resources