some_math_guy
some_math_guy

Reputation: 333

Evaluation order in ternary operator with increments

#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:

  1. First both a and be get incremented in (a++)>(b++)
  2. If for example the first one is greater, the ternary operator in c=((a++)>(b++) ? (a++) : (b++)), goes to (a++), so a increments again.
  3. 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?

Upvotes: 1

Views: 284

Answers (3)

Simon He
Simon He

Reputation: 106

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!

Upvotes: 0

Vlad from Moscow
Vlad from Moscow

Reputation: 311108

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++;
}

Upvotes: 2

John Bode
John Bode

Reputation: 123578

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.


  1. Although within that expression either a++ or b++ may be evaluated first, since the > operator doesn't force left-to-right evaluation.

Upvotes: 2

Related Questions