use*_*445 5 c++ compiler-construction gcc operator-precedence
可能重复:
未定义的行为和序列点
我不确定这是否是一个gcc bug,所以我会问:
unsigned int n = 0;
std::cout << n++ << n << ++n;
Run Code Online (Sandbox Code Playgroud)
gcc给出了非常奇怪的结果:AFAICT是不可能的"122".因为<<是左关联的,它应该是相同的:
operator<<(operator<<(operator<<(std::cout, n++), n), ++n)
Run Code Online (Sandbox Code Playgroud)
并且因为在评估参数之前和之后存在一个序列点,所以n在两个序列点之间永远不会被修改两次(甚至访问) - 因此它不应该是未定义的行为,只是未指定的评估顺序.
所以AFAICT的有效结果将是:111 012 002 101
没有别的
在评估参数和调用函数之间有一个序列点.在评估不同的参数之间没有序列点.
让我们看一下最外面的函数调用:
operator<<(operator<<(operator<<(std::cout, n++), n), ++n)
Run Code Online (Sandbox Code Playgroud)
争论是
operator<<(operator<<(std::cout, n++), n)和
++n未指明哪些是首先评估的.还允许在计算第二个参数时部分评估第一个参数.
从标准部分[intro.execution](第3225号草案的措辞):
如果甲是不是之前测序 乙和乙没有之前测序甲,然后甲和乙的未测序.[ 注意: 未经测试的评估的执行可能会重叠.- 结束说明 ]
除非另有说明,否则对单个运算符的操作数和单个表达式的子表达式的评估是不确定的.[ 注意:在程序执行期间不止一次评估的表达式中,不需要在不同的评估中对其子表达式进行无序和不确定顺序的评估.- 结束注释 ]在运算符的结果的值计算之前,对运算符的操作数的值计算进行排序.如果对标量对象的副作用相对于同一标量对象的另一个副作用或使用相同标量对象的值进行的值计算未被排序,则行为未定义.
因为在同一个标量对象上有多个副作用的操作相互之间没有顺序,所以你处于未定义行为的领域,甚至999是允许的输出.
编译器错误的第一条规则:这可能不是编译器错误,而是您的误解。在同一语句中使用后缀和前缀运算符会导致未定义的行为。尝试使用该-Wall选项为您提供更多警告并向您展示代码中的潜在缺陷。
让我们看看 GCC 4.2.1 在询问以下警告时告诉我们什么test.cpp:
#include <iostream>
int main() {
unsigned int n = 0;
std::cout << n++ << n << ++n << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我们编译时:
$ g++ -Wall test.cpp -o test
test.cpp: In function ‘int main()’:
test.cpp:5: warning: operation on ‘n’ may be undefined
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1480 次 |
| 最近记录: |