简体   繁体   中英

Is int a = ++i + ++i undefined behaviour?

Consider the following code:

int main(){
  int i = 0;
  int a = ++i + ++i;
}

I can't find any information that says that the operands of + are unsequenced. So according to the standard, the sequence of operands of binary + are indeterminately sequenced.

[intro,excution]/15

Given any two evaluations A and B, if A is sequenced before B (or, equivalently, B is sequenced after A), then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced. [ Note: The execution of unsequenced evaluations can overlap. — end note ]

Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which.[ Note: Indeterminately sequenced evaluations cannot overlap, but either could be executed first. — end note ]

The quote means that the evaluation of A can occur before B or the evaluation of B can occur before A. And the execution of unsequenced evaluations can overlap , whereas indeterminately sequenced evaluations cannot overlap , which are different.

We know the modification of i always occurs before value computation of i due to prefix ++ .

Then according to the rules:

Evaluation of an expression (or a subexpression) in general includes both value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and initiation of side effects

If a side effect on a memory location is unsequenced relative to either another side effect on the same memory location or a value computation using the value of any object in the same memory location, and they are not potentially concurrent, the behavior is undefined

So regardless of whether the evaluation of A is before B or the converse, there are no side effects related to corresponding value computation or side effect for ++i + ++i; . Because indeterminately sequenced evaluations cannot overlap, one of the two evaluation must be completely executed before the other. The evaluation includes both value computation and side effect. Therefore, one increment to i is evaluated before the other.

Unsequenced evaluations, however, follow different rules, so the confusion will be resolved if the evaluations of operands of binary + are unsequenced rather than indeterminately sequenced. If I missed something in the standard in the analysis above, please correct me.

Update

I found the following sentence, which seems to suggest that the evaluations are unsequenced:

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced .

However, I don't know how to understand the sentence correctly. I came up with two interpretations:

For an operator A, the evaluations of the operands of A are unsequenced with each other; for an expression B, the evaluations of the subexpressions of B are unsequenced with each other.

and

Take evaluations of operands of individual operators as A. Take evaluations of subexpressions of individual expressions as B. A is unsequenced with B.

Which interpretation is correct?

The standard text seems 1 to imply that the behavior is undefined.

  • in <a>+<b> the evaluations of <a> and <b> are unsequenced 2,3
  • the two parts have side effect that affect the same memory location

(1) This part is in my opinion unambiguous and clear, but I'm not sure there are not other parts that are saying the opposite or that some higher level concept (eg what is the execution of a program) is not logically broken because of contradicting rules. Given the complexity of C++ I would actually be quite surprised of no errors being present.

(2) In case of an overloaded operator+ they would be indeterminately sequenced (as the rules are the same as for a function call, thus NOT undefined behavior: 8.5.1.2[5] of N4713 says "The postfix-expression is sequenced before each expression in the expression-list and any default argument. The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter") but for native int s this does not apply and the behavior is undefined.

(3) The text says "Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced". Of course for unary operators the question is irrelevant (there is no ordering to talk about) and for the ternary ?: operator there are special sequencing rules. The part about "subexpressions" is to cover cases like a[++i][++i] where a is for example a char ** : in this case the two identical sub-expressions ++i are unsequenced and with side effects modifying the same memory location and thus undefined behavior. I think the paragraph is actually more complex than necessary because operands of an operator are also subexpressions of an expression thus the last part was sufficient.

Let me give a answers to make answers of the question more clealy. Firstly,consider the following sentence

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.

the sentence can be splited two

1.Except where noted,evaluations of operands of individual operators are unsequenced.
2.Except where noted,evaluations of subexpressions of individual expressions are unsequenced.

So,what does the 1 section mean?It means a set X consist of these operands of a operator and every element of the set X is unsequenced with each other,they are unsequenced.The sentence 2 is similar to sentence 1,It just make the set X consist of these subexpression of a expression.

Those statements of binary operator + are described in [expr.additive] and these's nothing about sequence of operands in that section,So,the rules 1 performed on the operator.Hence,as the standard say that unsequence can overlap,what does it mean?It means that "the parts of each evaluation can even be interleaved together"(@Ben Voigt said in the comment).So,for ++i + ++i ,it's typically of case:

If a side effect on a memory location is unsequenced relative to either another side effect on the same memory location or a value computation using the value of any object in the same memory location, and they are not potentially concurrent, the behavior is undefined

So, int a = ++i + ++i is undefined behaviour,the key point of this question is to understand the below sentence:

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM