简体   繁体   English

int a = ++i + ++i 是未定义的行为吗?

[英]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[介绍、执行]/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.给定任意两个评估 A 和 B,如果 A 在 B 之前排序(或者,等效地,B 在 A 之后排序),则 A 的执行应先于 B 的执行。如果 A 没有在 B 之前排序并且 B 没有排序在 A 之前,然后 A 和 B 是无序的。 [ 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.当 A 在 B 之前排序或 B 在 A 之前排序时,评估 A 和 B 的排序不确定,但未指定哪个。[注意:不确定排序的评估不能重叠,但可以先执行。 — 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.引用的意思是 A 的评估可以在 B 之前发生,或者 B 的评估可以在 A 之前发生。并且未排序的评估的执行可以重叠,而不确定序列的评估不能重叠,这是不同的。

We know the modification of i always occurs before value computation of i due to prefix ++ .由于前缀++ ,我们知道i i值计算之前。

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表达式(或子表达式)的评估通常包括值计算(包括确定 object 的身份以进行左值评估和获取先前分配给 object 的值以进行纯右值评估)和副作用的启动

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 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;因此,无论 A 的评估是在 B 之前还是相反,对于++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.因此, i的一个增量在另一个之前被评估。

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;对于算子 A,A 的操作数的求值是无序的; for an expression B, the evaluations of the subexpressions of B are unsequenced with each other.对于表达式 B,B 的子表达式的计算彼此之间是无序的。

and

Take evaluations of operands of individual operators as A. Take evaluations of subexpressions of individual expressions as B. A is unsequenced with B.将单个运算符的操作数的求值视为 A。将单个表达式的子表达式的求值视为 B。A 与 B 无序。

Which interpretation is correct?哪种解释是正确的?

The standard text seems 1 to imply that the behavior is undefined.标准文本似乎1暗示行为未定义。

  • in <a>+<b> the evaluations of <a> and <b> are unsequenced 2,3<a>+<b>中, <a><b> > 的评估是无序的2,3
  • the two parts have side effect that affect the same memory location这两个部分具有影响相同 memory 位置的副作用

(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. (1) 在我看来,这部分是明确和清晰的,但我不确定是否有其他部分说相反,或者某些更高级别的概念(例如,什么是程序的执行)在逻辑上没有被破坏,因为的相互矛盾的规则。 Given the complexity of C++ I would actually be quite surprised of no errors being present.鉴于 C++ 的复杂性,我实际上会对没有出现错误感到非常惊讶。

(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. (2) 在重载operator+的情况下,它们将被不确定地排序(因为规则与 function 调用相同,因此不是未定义的行为:N4713 的 8.5.1.2[5] 说“后缀表达式在每个表达式列表中的表达式和任何默认参数。参数的初始化,包括每个相关的值计算和副作用,相对于任何其他参数的顺序是不确定的”)但是对于本机int s 这并不适用,并且行为未定义。

(3) The text says "Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced". (3) 正文说“除非另有说明,对单个运算符的操作数和单个表达式的子表达式的求值是无序的”。 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.关于“子表达式”的部分是涵盖像a[++i][++i]这样的情况,其中a是例如char ** :在这种情况下,两个相同的子表达式++i是无序的并且有副作用修改相同的 memory 位置和未定义的行为。 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. 1. 除非另有说明,对单个运算符的操作数的评估是无序的。
2.Except where noted,evaluations of subexpressions of individual expressions are unsequenced. 2. 除非另有说明,对单个表达式的子表达式的评估是无序的。

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.那么,第 1 部分是什么意思?这意味着一个集合X由一个运算符的这些操作数组成,集合X的每个元素彼此之间是无序的,它们是无序的。句子 2 类似于句子 1,它只是使集合X由表达式的这些子表达式组成。

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:二元运算符+的那些语句在 [expr.additive] 中进行了描述,而这些与该部分中的操作数序列无关,因此,在运算符上执行的规则1因此,正如标准所说,不序列可以重叠,这是什么意思?这意味着“每个评估的部分甚至可以交错在一起”(@Ben Voigt 在评论中说)。所以,对于++i + ++i ,通常是这样的:

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 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:所以, int a = ++i + ++i是未定义的行为,这个问题的关键是理解下面的句子:

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.除非另有说明,否则单个运算符的操作数和单个表达式的子表达式的求值是无序的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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