Why is `i = ++i + 1` unspecified behavior?

2019-01-04 23:04发布

Consider the following C++ Standard ISO/IEC 14882:2003(E) citation (section 5, paragraph 4):

Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. 53) Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined. [Example:

i = v[i++];  // the behavior is unspecified 
i = 7, i++, i++;  //  i becomes 9 

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

—end example]

I was surprised that i = ++i + 1 gives an undefined value of i. Does anybody know of a compiler implementation which does not give 2 for the following case?

int i = 0;
i = ++i + 1;
std::cout << i << std::endl;

The thing is that operator= has two args. First one is always i reference. The order of evaluation does not matter in this case. I do not see any problem except C++ Standard taboo.

Please, do not consider such cases where the order of arguments is important to evaluation. For example, ++i + i is obviously undefined. Please, consider only my case i = ++i + 1.

Why does the C++ Standard prohibit such expressions?

15条回答
叼着烟拽天下
2楼-- · 2019-01-04 23:28

How about, we just all agree to never, never, write code like this? If the compiler doesn't know what you want to do, how do you expect the poor sap that is following on behind you to understand what you wanted to do? Putting i++; on it's own line will not kill you.

查看更多
对你真心纯属浪费
3楼-- · 2019-01-04 23:29

i = v[i++]; // the behavior is unspecified
i = ++i + 1; // the behavior is unspecified

All the above expressions invoke Undefined Behavior.

i = 7, i++, i++; // i becomes 9

This is fine.

Read Steve Summit's C-FAQs.

查看更多
Luminary・发光体
4楼-- · 2019-01-04 23:30

Argument by analogy: If you think of operators as types of functions, then it kind of makes sense. If you had a class with an overloaded operator=, your assignment statement would be equivalent to something like this:

operator=(i, ++i+1)

(The first parameter is actually passed in implicitly via the this pointer, but this is just for illustration.)

For a plain function call, this is obviously undefined. The value of the first argument depends on when the second argument is evaluated. However with primitive types you get away with it because the original value of i is simply overwritten; its value doesn't matter. But if you were doing some other magic in your own operator=, then the difference could surface.

Simply put: all operators act like functions, and should therefore behave according to the same notions. If i + ++i is undefined, then i = ++i should be undefined as well.

查看更多
兄弟一词,经得起流年.
5楼-- · 2019-01-04 23:32

C/C++ defines a concept called sequence points, which refer to a point in execution where it's guaranteed that all effects of previous evaluations will have already been performed. Saying i = ++i + 1 is undefined because it increments i and also assigns i to itself, neither of which is a defined sequence point alone. Therefore, it is unspecified which will happen first.

查看更多
时光不老,我们不散
6楼-- · 2019-01-04 23:36

Update for C++11 (09/30/2011)

Stop, this is well defined in C++11. It was undefined only in C++03, but C++11 is more flexible.

int i = 0;
i = ++i + 1;

After that line, i will be 2. The reason for this change was ... because it already works in practice and it would have been more work to make it be undefined than to just leave it defined in the rules of C++11 (actually, that this works now is more of an accident than a deliberate change, so please don't do it in your code!).

Straight from the horse's mouth

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#637

查看更多
一夜七次
7楼-- · 2019-01-04 23:39

From ++i, i must assigned "1", but with i = ++i + 1, it must be assigned the value "2". Since there is no intervening sequence point, the compiler can assume that the same variable is not being written twice, so this two operations can be done in any order. so yes, the compiler would be correct if the final value is 1.

查看更多
登录 后发表回答