MSVC++:无符号整数和溢出的奇怪之处
我有以下代码:
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
string a = "a";
for(unsigned int i=a.length()-1; i+1 >= 1; --i)
{
if(i >= a.length())
{
cerr << (signed int)i << "?" << endl;
return 0;
}
}
}
如果我在 MSVC 中进行完全优化编译,我得到的输出是“-1?”。 如果我在调试模式下编译(无优化),我不会得到任何输出(预期)。
我认为标准保证无符号整数以可预测的方式溢出,因此当 i = (unsigned int)(-1), i+1 = 0,循环条件 i + 1 >= 1 失败。 相反,测试以某种方式通过了。 这是编译器错误,还是我在某处做了一些未定义的事情?
I've got the following code:
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
string a = "a";
for(unsigned int i=a.length()-1; i+1 >= 1; --i)
{
if(i >= a.length())
{
cerr << (signed int)i << "?" << endl;
return 0;
}
}
}
If I compile in MSVC with full optimizations, the output I get is "-1?". If I compile in Debug mode (no optimizations), I get no output (expected.)
I thought the standard guaranteed that unsigned integers overflowed in a predictable way, so that when i = (unsigned int)(-1), i+1 = 0, and the loop condition i + 1 >= 1 fails. Instead, the test is somehow passing. Is this a compiler bug, or am I doing something undefined somewhere?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我记得 2001 年就遇到过这个问题。我很惊讶它仍然存在。 是的,这是一个编译器错误。
优化器看到
理论上,我们可以通过将所有常量放在同一侧来优化它:
因为 i 是无符号的,所以它总是大于或等于零。
请参阅此新闻组讨论 此处。
I remember having this problem in 2001. I'm amazed it's still there. Yes, this is a compiler bug.
The optimiser is seeing
Theoretically, we can optimise this by putting all of the constants on the same side:
Because i is unsigned, it will always be greater than or equal to zero.
See this newsgroup discussion here.
ISO14882:2003,第 5 节,第 5 段:
(强调我的。)所以,是的,行为是未定义的。 该标准不保证整数上溢/下溢情况下的行为。
编辑:该标准在其他地方似乎略有冲突。
第 3.9.1.4 节说:
但第 4.7.2 和 .3 节说:
(强调我的。)
ISO14882:2003, section 5, paragraph 5:
(Emphasis mine.) So, yes, the behavior is undefined. The standard makes no guarantees of behavior in the case of integer over/underflow.
Edit: The standard seems slightly conflicted on the matter elsewhere.
Section 3.9.1.4 says:
But section 4.7.2 and .3 says:
(Emphasis mine.)
我不确定,但我认为您可能遇到了错误。
我怀疑问题在于编译器如何处理
for
控件。 我可以想象优化器会做什么:是否发生这种情况是另一回事,但这可能足以让优化器感到困惑。
使用更标准的循环公式可能会更好:
I'm not certain, but I think you are probably running foul of a bug.
I suspect the trouble is in how the compiler is treating the
for
control. I could imagine the optimizer doing:Whether that is what is happening is another matter, but it might be enough to confuse the optimizer.
You would probably be better off using a more standard loop formulation:
是的,我刚刚在 Visual Studio 2005 上对此进行了测试,它在调试和发布中的表现肯定有所不同。 我想知道2008年是否解决了这个问题。
有趣的是,它抱怨您从 size_t (.length 的结果)到 unsigned int 的隐式转换,但生成错误代码没有问题。
Yup, I just tested this on Visual Studio 2005, it definitely behaves differently in Debug and Release. I wonder if 2008 fixes it.
Interestingly it complained about your implicit cast from size_t (.length's result) to unsigned int, but has no problem generating bad code.