c++ while循环优化不能正常工作
C++ while loop optimization not working properly
我有这样的代码段:
#include <stdio.h>
int main(int argc, const char** argv)
{
int a = argv[0][0];
int b = argv[0][1];
while ((a >= 0) &&
(a < b))
{
printf("a = %dn", a);
a++;
}
return 0;
}
,我正在编译它与gcc-4.5 -02 -Wstrict-overflow=5
。
编译器对我大喊大叫warning: assuming signed overflow does not occur when changing X +- C1 cmp C2 to X cmp C1 +- C2
这到底是什么意思?
如果我是正确的,这个循环永远不会导致溢出,因为要使a递增,它必须小于另一个整数。
谁能给我解释一下这种行为?编译器正在优化将a + 1 < b
转换为a < b - 1
。然而,如果b
是INT_MIN
,那么这将下溢,这是行为的变化。这就是它的警告。
当然,您可能会说这是不可能的,但是编译器的资源有限,通常不会对数据路径进行深入分析。
增加b >= 0
可能解决问题的检查
Edit
:另一种可能性是它将a >= 0
移到循环之外,因为(假设没有溢出)它永远不会改变。同样,该假设可能对所有输入都无效(例如,如果b
为负)。您需要检查最终的程序集,看看它实际做了什么。
c++标准规定,如果有符号整数计算产生的结果超出该类型的可表示范围,则该行为未定义。整数溢出为UB。一旦发生了UB,实现就可以自由地做任何它喜欢的事情。
许多编译器在显式假设不发生UB的情况下应用优化。或者,如果它是,代码可能是错误的,但这是你的问题!)
这个编译器通知你,它正在应用这样的优化计算,它无法从分析代码中确定UB不发生。
你的选择通常是:
- 确信不可能发生UB,忽略警告。
- 允许UB发生并承担后果。
- 重写代码,这样UB真的不会发生,编译器知道它不会发生,警告应该消失。
我推荐最后一个选项。a
和b
的简单范围测试应该足够好了。
我的猜测是编译器发出这个错误,因为循环处理完全未知的值,它无法很好地分析数据流,以确定UB是否会发生。
我们凭借优越的推理能力可以说服自己UB不可能发生,所以我们可以忽略这个错误。事实上,仔细阅读错误消息可能会让我们问它是否相关。C1
和C2
这两个常量在哪里?
我们可能还注意到a
永远不会变为阴性,那么为什么在循环中要进行该测试?我可能会重写代码来抑制错误,(但从经验来看,这可能会弄巧成拙)。试试这个,看看会发生什么(避免不必要的括号混乱):
if (a >= 0) {
while (a < b) {
...
++a;
}
}
编译器警告您的是,它假设在原始代码中没有发生有符号溢出。
警告并不意味着"我即将编写的优化可能会导致引入溢出。"
换句话说,如果你的程序依赖于溢出(即不是高度可移植的),那么编译器正在做的优化可能会改变它的行为。(所以请自己验证这段代码不依赖于溢出)。
例如,如果您有"a + b> c",并且您依赖于该测试在a + b算术包装时失败(典型的两个的互补行为),那么如果它碰巧在代数上转换为"a> c - b",那么它可能成功,因为c - b可能碰巧没有溢出,并产生小于a的值。
注意:只有C程序可以调用未定义行为。当编译器不正确时,它们是"不一致的"。如果编译器对符合(C标准)的代码做了错误的事情,那么它只能是不符合(C标准)的。一个改变了正确的,可移植的行为的优化是一个不符合的优化。
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 为什么STD ::计数将常数传递给Lambda,而不是在弦上工作时而不是字符
- sdl软件渲染器不工作,工作在硬件加速的一个
- C++程序已停止工作-求解常微分方程