AFAIK gcc不提供这样的选项。正如您所引用的,该标准说:
N3690 - §5.8.3
E1 >> E2 的值是 E1 右移 E2 位位置。如果 E1 具有无符号类型或 E1 具有带符号类型和非负值,则结果的值是 E1/2E2 的商的整数部分。如果 E1 具有带符号类型和负值,则结果值是实现定义的。
这意味着做
int si = -1;
int right = si >> 1;
结果可能会或可能不会产生-1。它是实现定义的。这意味着编译器不会被迫产生类似“其他编译器可能会以另一种方式执行此操作”的警告。
这种选择的一些原因如下。
原始的 K&R 段落说:
“右移无符号数量,用 0 填充空位。右移有符号数量将在某些机器(例如 PDP-11)上填充符号位(算术移位),而在其他机器上填充 0 位(逻辑移位)。”
这意味着操作依赖于架构。这背后的原因是一些架构在做两者之一但不是两者都快速。
这个原因加上符号扩展移位的有用性是微不足道的这一事实使得标准选择将其保留为“实现定义”。通过“符号扩展移位的有用性”,我的意思是在算术上右移一个负有符号整数不能作为正对应物(因为在右边丢失 1 会使负数更小,即模数更大)
+63 >> 1 = +31 (integral part of quotient E1/2E2)
00111111 >> 1 = 00011111
-63 >> 1 = -32
11000001 >> 1 = 11100000
进一步阅读的参考资料:
https://stackoverflow.com/a/1857965/1938163
http://www.ccsinfo.com/forum/viewtopic.php?t=45711
https://isocpp.org/std/the-standard
编辑:如果上面没有解决问题(即代码是有效的,编译器为什么要警告呢?)我提供了第二种解决方案:AST matchers
如此处所述:http: //eli.thegreenplace.net/2014/07/29/ast-matchers-and-clang-refactoring-tools/您可以编写一些代码来快速识别所有右移-with-signed-程序中的整数点。
将其视为“编写我的小型单任务静态分析检查器”。
编辑 2:您也可以尝试其他静态分析工具,clang 有一个-fsanitize=shift选项可以为您工作。AFAIK 还为gcc实现了一个未定义的行为清理程序,可以帮助诊断这些错误。我没有关注这个故事,但我想你也可以尝试一下。