Using the increment of the ternary operator in C

As an example, after use

int a = 5, b = 6; x = (a < b) ? a++ : b++; 

x gets the value of a, which is 5, and the increment to 6, which is expected.

When i use

 a = (a < b) ? a++ : b++; 

There is still 5 left after this line.

But

 a = (a++ < b++) ? a : b; 

a now 6.

Why is this happening and why the increment operator is not executed in the first case?

EDIT: just for clarification, I ask why this happens when I use these lines separately, one after the other, and not all three at the same time.

+6
source share
4 answers

Both cases are related to some kind of undefined behavior, because you increase a by returning a and assigning a on the left side within two points of the sequence. 3 is required for a well-defined result.

In this case: a = (a < b) ? a++ : b++; a = (a < b) ? a++ : b++;

  • if a less than b
  • a returned (value = 5) as a result of the ternary operator
  • a increases (value = 6).
  • the result of ternary operator (5) is assigned to the left side of the variable a (rewriting 6)

The order of steps 3 and 4 is not defined. This is equivalent to a = a++;

In this case: a = (a++ < b++) ? a : b; a = (a++ < b++) ? a : b;

  • If a less than b
  • a and b increase (no matter which is smaller)
  • a returns as a result of the triple operator
  • assigned to the left side the variable a

The order of steps 2 and 3 is not clearly defined.

It is important to keep track of sequence points in such cases. Relevant Rules:

  • The first expression of the ternary operator to the left of ? sequenced before the second or third expression. And any of them is sequenced before the appointment.
  • ? comparison sequenced before ?
  • In expressions such as a++ , the value is returned before the increment

Undefined behavior:

  • In expressions like a = a++; there is no sequence point between the (post) increment a and the destination a on the left side. Both options are executed after returning the initial value a
  • In expressions like a++ ? a : b a++ ? a : b there is no sequence point between the (post) increment of a and the return of a from the ternary operator. Both occur after ?
+2
source
 a = (a < b) ? a++ : b++; 

here we saved a to a and then increased it. But it looks like

 a = a++; // as a<b 

which shows undefined behavior.

 a = (a++ < b++) ? a : b; 

here a increases during comparison, so now a is 6, which is stored in a.

+4
source

There is an error in one line that gives an unexpected result: you cannot change an object (here a ) twice in one expression without separating them with a "sequence point".

? in the other, this is the point of the sequence, so it works.

If you do this (change twice without a sequence point), the behavior of your program will become undefined. That is, you cannot make a reasonable assumption about what the program should produce, and, therefore, you will see unexpected results, which will even vary depending on the compiler and its version.

+1
source

From the horse mouth :

6.5 Expressions
...
2 If the side effect of a scalar object is independent of another side effect on the same scalar object or calculating a value using the value of the same scalar object, the behavior is undefined. If there are several valid orders of expression subexpression, the behavior is undefined, if such an inconsistent side of the effect occurs in any of the orders. 84)
84) This paragraph displays undefined expression expressions such as
  i = ++i + 1; a[i++] = i; 
letting
  i = i + 1; a[i] = i; 
6.5.15 Conditional statement
...
4 The first operand is evaluated; there is a point in the sequence between its evaluation and the evaluation of the second or third operand (depending on what is being evaluated) . The second operand is evaluated only if the first is compared not equal to 0; the third operand is evaluated only if the first is compared to 0; the result is the value of the second or third operand (depending on what is being evaluated), is converted to the type described below. 110)
110) The conditional expression does not give an lvalue.
6.5.16 Assignment Operators
...
3 The assignment operator stores the value in the object indicated by the left operand. the assignment expression has the value of the left operand after the assignment, 111) but is not an lvalue. The type of an assignment expression is the type that the left operand must have after lvalue conversion. A side effect of updating the stored value of the left operand is to order after calculating the values โ€‹โ€‹of the left and right operands. Estimates of operands are not affected.
111) Implementations are allowed to read an object to determine a value, but not required, even when the object is of an unstable type.

In expression

 a = (a < b ) ? a++ : b++ 

there is a sequence point between evaluation (a < b) and a++ , but there is no sequence point between evaluation of a on the LHS of the = operator and a++ ; thus, the behavior is undefined.

In expression

 a = (a++ < b++) ? a : b 

? there a sequence point between (a++ < b++) and a on the RHS operator ? but there is no sequence point between a on the LHS operator = and (a++ < b++) ; again, the behavior is undefined.

0
source

All Articles