为什么 i = ++i + 2 是未定义的行为?
why i = ++i + 2 is undefined behavior?
我读过一些关于求值顺序的内容,我理解一些由求值顺序引起的错误。
我的基本规则来自文本和示例:
- Order of operand evaluation is independent of precedence and associativity.
- In most cases, the order is largely unspecified.
所以对于这样的表达式:int i = f1() * f2();
f1 and f2 must be called before the multiplication can be done. After all, it is their results that are multiplied. However, we have no way of knowing whether f1 will be called before f2 or vice versa.
未定义的行为示例:
int i = 0;
cout << i << " " << ++i << endl;
我的理解是:我把 i
和 ++i
当作一个函数。我不知道哪个先评估,所以第一个 i
可能是 0
或 1
并且(规则)是有道理的。
while(beg != s.end())
*beg = toupper(*beg++); //Just another example.
我认为理解这一点的关键是将每个操作数视为一个 "evaluation unit",人们不知道这些单元内的评估顺序,但可以知道 每个单元中的顺序.
但是对于i = ++i + 2
reference here,为什么会出错呢?我无法用我自己的结论来解释。
左边的 i
用作 左值 而 不是指针 。 ++i
只是改写原来的值,不改变存储地址。如果先评估或后评估,可能有什么问题?我的规则在这里失败了。
很长,但请尽量提供足够的背景信息,感谢您的耐心等待。
我不知道答案中经常提到的序列点。所以我想我需要先阅读一些相关内容。顺便说一句,辩论不是很有帮助,对于新手来说,只是想知道为什么它被认为是错误的,就像 C++11 之前一样?
我找到了这个答案 Undefined behavior and sequence points 很好地解释了为什么 i = ++i + 2
在 C++11
之前是未定义的行为
你在i = ++i + 2
中的两个"subfunctions"是=
运算符的显式赋值和++
运算符的隐式赋值。
预增运算符定义为return变量的递增值,这肯定用于加法(由+
运算符执行)。但是,它没有定义,当 增量值应该存储回 i
.
因此,未定义 i
的最终值是 old_i incremented plus 2
还是只是 old_i incremented
。
C++11 有新的排序规则。特别是,对于预增量(++i
),副作用(写入新值)在进一步使用新的增量值之前进行排序。由于赋值 i=
在其右侧求值之后排序,这意味着写入 ++i
在写入 i=(++i + 2)
之前传递排序
i=(i++ + 2)
另当别论。对于 post-increment,副作用是 sequenced-after,这意味着两个赋值不再相对于彼此排序。那是未定义的行为。
我读过一些关于求值顺序的内容,我理解一些由求值顺序引起的错误。
我的基本规则来自文本和示例:
- Order of operand evaluation is independent of precedence and associativity.
- In most cases, the order is largely unspecified.
所以对于这样的表达式:int i = f1() * f2();
f1 and f2 must be called before the multiplication can be done. After all, it is their results that are multiplied. However, we have no way of knowing whether f1 will be called before f2 or vice versa.
未定义的行为示例:
int i = 0;
cout << i << " " << ++i << endl;
我的理解是:我把 i
和 ++i
当作一个函数。我不知道哪个先评估,所以第一个 i
可能是 0
或 1
并且(规则)是有道理的。
while(beg != s.end())
*beg = toupper(*beg++); //Just another example.
我认为理解这一点的关键是将每个操作数视为一个 "evaluation unit",人们不知道这些单元内的评估顺序,但可以知道 每个单元中的顺序.
但是对于i = ++i + 2
reference here,为什么会出错呢?我无法用我自己的结论来解释。
左边的 i
用作 左值 而 不是指针 。 ++i
只是改写原来的值,不改变存储地址。如果先评估或后评估,可能有什么问题?我的规则在这里失败了。
很长,但请尽量提供足够的背景信息,感谢您的耐心等待。
我不知道答案中经常提到的序列点。所以我想我需要先阅读一些相关内容。顺便说一句,辩论不是很有帮助,对于新手来说,只是想知道为什么它被认为是错误的,就像 C++11 之前一样?
我找到了这个答案 Undefined behavior and sequence points 很好地解释了为什么 i = ++i + 2
在 C++11
你在i = ++i + 2
中的两个"subfunctions"是=
运算符的显式赋值和++
运算符的隐式赋值。
预增运算符定义为return变量的递增值,这肯定用于加法(由+
运算符执行)。但是,它没有定义,当 增量值应该存储回 i
.
因此,未定义 i
的最终值是 old_i incremented plus 2
还是只是 old_i incremented
。
C++11 有新的排序规则。特别是,对于预增量(++i
),副作用(写入新值)在进一步使用新的增量值之前进行排序。由于赋值 i=
在其右侧求值之后排序,这意味着写入 ++i
在写入 i=(++i + 2)
i=(i++ + 2)
另当别论。对于 post-increment,副作用是 sequenced-after,这意味着两个赋值不再相对于彼此排序。那是未定义的行为。