Why is the chained increment / decment prefix for the built-in type not UB for C ++?

In cpprefernce.com an example for incrementing the prefix is ​​the following code:

int n1 = 1; ... int n3 = ++ ++n1; 

Why does chained growth in this case not lead to UB? Is the rule no more than once amended, not broken in this case?

+8
c ++ prefix-operator
source share
2 answers

In C ++ 11 and later, UB occurs when there are two records or records and reads that have no sequence and access to the same memory location. But ++x equivalent to x+=1 , therefore ++ ++n1 equivalent to (n1+=1)+=1 , and here the reads and writes occur in strict sequence due to the properties of the assignment operators and compound assignment: first read n1 , then write one plus the original value, then the resulting value is read again, then one plus this value is written back.

In C ++ 03, it was UB, because of the old rule that you are referring to: there is no sequence point between the two modifications. But in C ++ 11 there are no more sequence points; instead, there is an “ordered to” partial order.

+11
source share

See Brian's answer for simpler terms.

This is legal because the C ++ standard says so, the emphasis is mine. We are following the C ++ 14 project

5.3.2 Increment and decrement [expr.pre.incr]

The ++ prefix operand is modified by adding 1 or true if it is a bool (this usage is deprecated). An operand may be a modifiable naming convention. The type of operand must be arithmetic or a pointer to a fully defined type of object. The result is an updated operand; it is an lvalue , and it is a bit field, if the operand is a bit field. If x is not of type bool, the expression ++ x is equivalent to x + = 1

So this is completely legal

 #include <iostream> using namespace std; int main(){ int x =8; int y = ++ ++ ++ ++ ++ ++ ++ ++ x; cout << x << " " << y; } 

Exit

 16 16 

1.9 Program Execution [intro.execution]

15 ... 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 ....

And he attached an example:

 void f(int, int); void g(int i, int* v) { i = v[i++]; // the behavior is undefined i = 7, i++, i++; // i becomes 9 i = i++ + 1; // the behavior is undefined i = i + 1; // the value of i is incremented f(i = -1, i = -1); // the behavior is undefined } 
+2
source share

All Articles