首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MSVC++:对无符号整数和溢出的陌生感

MSVC++:对无符号整数和溢出的陌生感
EN

Stack Overflow用户
提问于 2009-03-24 02:36:00
回答 3查看 347关注 0票数 8

我得到了以下代码:

代码语言:javascript
运行
复制
#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失败。相反,测试正在以某种方式通过。这是一个编译器错误,还是我正在做一些未定义的事情?

EN

回答 3

Stack Overflow用户

发布于 2009-03-24 02:52:48

ISO14882:2003,第5节,第5款:

如果在表达式求值期间,结果未在数学上定义或不在其类型的可表示值范围内,则行为是未定义的,除非这样的表达式是常量表达式(5.19),在这种情况下,程序是病态的。

(重点是我的。)所以,是的,行为是未定义的。该标准不保证在整数溢出/下溢的情况下的行为。

编辑:该标准似乎在其他地方的问题上略有冲突。

第3.9.1.4节规定:

被声明为无符号的

无符号整数应遵守以2n为模的算术法则,其中n是该特定大小的整数的值表示中的位数。

但是4.7.2节和.3说:

2)如果目标类型是无符号类型,则得到的值是与源整数(模2 n,其中n是用于表示无符号类型的位数)相同的最小无符号整数。注意:在二进制补码表示中,这种转换是概念性的,位模式没有变化(如果没有截断)。

3)如果目标类型是有符号的,则如果可以在目标类型(和位字段宽度)中表示,则该值保持不变;否则,该值由实现定义。

(重点是我的。)

票数 4
EN

Stack Overflow用户

发布于 2009-03-24 02:50:47

我不确定,但我认为你可能遇到了一个bug。

我怀疑问题出在编译器处理for控件的方式上。我可以想象优化器会做什么:

代码语言:javascript
运行
复制
for(unsigned int i=a.length()-1; i+1 >= 1; --i)   // As written

for (unsigned int i = a.length()-1; i >= 0; --i) // Noting 1 appears twice

for (unsigned int i = a.length()-1; ; --i)   // Because i >= 0 at all times

这是否是正在发生的事情是另一回事,但这可能足以使优化器感到困惑。

使用更标准的循环公式可能会更好:

代码语言:javascript
运行
复制
for (unsigned i = a.length()-1; i-- > 0; )
票数 1
EN

Stack Overflow用户

发布于 2009-03-24 02:55:24

是的,我刚刚在Visual Studio2005上测试了这一点,它在Debug和Release中的表现绝对不同。我想知道2008年是否能解决这个问题。

有趣的是,它抱怨从size_t (.length的结果)到unsigned int的隐式强制转换,但生成糟糕的代码没有任何问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/675976

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档