Pre-increment versus post-increment in terms of sequence points

In this response, there are a few examples of well-defined and vague expressions. I am particularly interested in two of them:

(6) i = i++ + 1;    // Undefined Behaviour
(7) i = ++i + 1;    // Well-defined Behaviour

      

This means there is a difference between pre-increment and post-increment in terms of sequence points and well-defined / undefined / undefined behavior, but I don't understand where the difference comes from.

There is a sample code in the standard draft ( N4618 ) ([intro.execution], pt 18)

i = i++ + 1; // the value of i is incremented

i = i++ + i; // the behavior is undefined

Which, as I understand it, means that the expression i = i++ + 1

must be well defined and the value of the variable i

must increase by 1

as a result of that expression. However, this code, running in MSVS 2015, increments i

by 2

.

So what's going on in the expression i = i++ + 1

? Is this well-defined, undefined, implementation-defined, or undefined behavior? And is there any difference between pre-increment and post-increment in this and similar expressions in terms of sequence points and UB as stated in the original answer? And why does Visual Studio show different behavior from the standard?

Also note that I am primarily interested in modern c ++ (14/17).

+3


source to share


2 answers


What's going on in the expression i = i++ + 1

? Is it correct, undefined, defined, or undefined behavior?

This exact example is given in the standard, how lucky are we?

N4296 1.9.15 [intro.execution]

i = i++ + 1; // the behavior is undefined

Of course, we would like to know why too. Below is the following standard quote:

N4296 1.9.15 [intro.execution]

[...] Calculations of operator operand values โ€‹โ€‹are sequenced before calculating the operator result value. [...]



This tells us that the amount will happen before the assignment (duh, how else does she know what to assign!), But that doesn't guarantee that the increment will happen before or after the assignment, now we're in troubled waters ...

N4296 1.9.15 [intro.execution]

[...] If a side effect of a scalar object does not depend on another side effect on the same scalar object or the computation of a value using the value of the same scalar object and they are not potentially parallel (1.10), the behavior is undefined. [...]

The assignment operator has a side effect on the value i

, which means that we have two side effects (the other is the assignment being performed i++

) on the same scalar object that are not subject to a sequence that is undefined.

Why does Visual Studio show different behavior?

This is not true. The standard says it is undefined, which means it can do anything from what you wanted to something completely different, it just happens to be behavior that the compiler burst out!

+1


source


i = ++i + 1; // Well-defined Behaviour

This means that there is a difference between pre-increment and post-incidence in terms of sequence points and well-defined / unspecified / undefined behavior, but I don't understand where the difference comes from.

I believe the message is incorrect in several ways. Quoting the same section as them, emphasizing mine:

C ++ 11 1.9 / 15
Operand Values โ€‹โ€‹Evaluation An operator is ordered before computing the operator's result value. If a side effect of a scalar object does not affect any other side effect on the same scalar object, or the computation of a value using the value of the same scalar object, the behavior is undefined .

Then the assignment operator:

C ++ 11 5.17
  In all cases, the assignment is done after evaluating the value of the right and left operands and before evaluating the value of the assignment expression.

It is known that the computation of a value or the right and left operands are not sequenced. (This is explicitly stated in C11 1) which otherwise has completely identical text as C ++ 11.)

Assuming that the i = ++i + 1;

side effect in the expression ++i

does not affect the computation of the value of the left operand i

. So the undefined behavior is 1.9 / 15. And UB has nothing to do with the side effect of prescribing.

As far as the expression is concerned i = i++ + 1;

, the side effect of assignment, like C ++ 11, is explicitly sequenced after the value is evaluated, but before the value of the expression as a whole is evaluated. Evaluation of the value is i++

not a problem according to 5.2.6 "Evaluation of the values โ€‹โ€‹of the ++ expression is sequenced before the operand object is modified". According to the nature of postfix ++, the side effect of the update i++

should be ordered after the value of the entire expression is evaluated. This is clear behavior as far as I know.



Therefore, the correct text should be

(6) i = i++ + 1;    // Well-defined Behaviour
(7) i = ++i + 1;    // Undefined Behaviour

      

Apparently, there was a flawed example in C ++ 11 1.9 / 15 i = i++ + 1; // the behavior is undefined

, which was fixed in later versions of the standard.

NOTE. None of this has anything to do with changing the wording about sequence points!


1) C11 6.5.16 / 3

A side effect of updating the stored value is that the left operand is sequenced after calculating the values โ€‹โ€‹of the left and right operands. Operand evaluations are not affected.

0


source







All Articles