【发布时间】:2019-01-17 23:17:51
【问题描述】:
我阅读了 C++17 标准 $8.5.7.4:
表达式 E1 在表达式 E2 之前排序。
用于移位运算符。
另外cppreference 规则 19 说:
在移位运算符表达式 E1E2 中,E1 的每个值计算和副作用都排在 E2 的每个值计算和副作用之前
但是当我尝试使用 gcc 7.3.0 或 clang 6.0.0 编译以下代码时
#include <iostream>
using namespace std;
int main() {
int i = 5;
cout << (i++ << i) << endl;
return 0;
}
我收到以下 gcc 警告:
../src/Cpp_shift.cpp: In function ‘int main()’:
../src/Cpp_shift.cpp:6:12: warning: operation on ‘i’ may be undefined [-Wsequence-point]
cout << (i++ << i) << endl;
~^~
叮当警告是:
warning: unsequenced modification and access to 'i' [-Wunsequenced]
我使用以下命令编译:
g++ -std=c++17 ../src/Cpp_shift.cpp -o Cpp_shift -Wall
clang++ -std=c++17 ../src/Cpp_shift.cpp -o Cpp_shift -Wall
在这两种情况下,我都得到了预期的 320 作为输出 (5 * 2 ^ 6)
有人可以解释为什么我会收到此警告吗?我忽略了什么吗?我还阅读了this 相关问题,但它没有回答我的问题。
编辑:所有其他变体 ++i << i、i << ++i 和 i << i++ 都会产生相同的警告。
edit2:(i << ++i) 导致 clang(正确)320 和 gcc(错误)384。如果++ 位于E2,gcc 似乎会给出错误的结果,(i << i++) 也会给出错误的结果。
【问题讨论】:
-
看起来诊断是由使用旧规则的逻辑创建的。我不确定何时引入
<<的排序,但可能直到 C++14 或 C++17 才引入。因为它显然是一个错误,理想情况下应该报告。 -
@KorelK 当我删除
-Wall时,对于(i << ++i),我仍然得到与 gcc 相同的错误结果。在没有-Wall的情况下,clang 也会发出警告。 -
@xaxxon gcc 给 320 没有
-fsanitize=undefined和 160 有它 -
C++17 排序还没有完全被 GCC 实现。具有赋值运算符的 GCC 中相同性质的问题:stackoverflow.com/questions/51511102/…
标签: c++ language-lawyer c++17 sequence-points