为什么它在-2147483648和(int)-2147483648之间有所不同

时间:2012-09-27 11:51:43

标签: c++ integer overflow

当我在使用MinGW的GCC编译的Windows7 x64下运行以下代码时,结果似乎是下溢的:

cout<<-2147483648 ;    //Output: 2147483648

但是当我将它分配给整数变量时,或者只是简单地将其转换为int类型:

cout<<(int)-2147483648 ; //Output: -2147483648 

那么,我的代码的早期版本出了什么问题?我不是int类型吗?或整数的下界究竟是什么? 非常感谢。

4 个答案:

答案 0 :(得分:11)

2147483648不适合您的系统中的int或long,因此它被视为unsigned long类型的常量。 (编辑:正如ouah在评论中指出的那样,它是标准C ++中的未定义行为,但是你的编译器接受它作为扩展。)可以否定无符号整数值,但会产生另一个无符号整数值,绝不是负数。否定2147483648UL产生2147483648UL(假设,就像你的系统一样,unsigned long是32位类型)。

将其转换为int会产生实现定义的结果,通常是您看到的结果,但不一定如此。您可以通过编写-2147483647 - 1来获得所需的结果而无需任何转换。

答案 1 :(得分:3)

  

那么,我的代码的早期版本出了什么问题?

据推测,您使用的是2011年之前的编译器,而您的系统long上有32位。值(-2 31 )不能保证适合long,因此可能会溢出。这给出了未定义的行为,所以你可以看到任何东西。

您看到的特定值(2 31 )最可能的解释是,在C ++中没有定义的行为时,您的编译器使用旧的C90规则,并将值转换为unsigned long

  

我不是int类型吗?

2011年之前,如果值int可以表示int,则为long,否则为long long,如果这还不够,则为未定义的行为。 C ++ 11添加了long类型,并允许在int不够大的情况下用于整数文字。

  

或整数的下限是什么?

具有N位的有符号整数类型具有至少-2 (N-1) +1至2 (N-1) -1的范围。您的值为-2 31 ,这超出了32位有符号类型的范围。

该语言未指定整数类型的确切大小;只是long必须至少有16位,long long至少32位,(自2011年起){{1}}至少64位。

答案 2 :(得分:2)

首先,了解there are no negative integer literals

非常重要

其他人已经解释了为什么OP的特定编译器的行为与它一样。但是对于记录,这是编译器应该在32位系统上的行之间做的事情:

  • 您的号码为2147483648,不能使用二进制补码格式的32位签名int
  • 由于它是十进制数(没有U,L或类似的后缀),编译器会检查其内部类型表(1)是否存在这样的整数常量。它的工作方式如下:尝试将其放入int,如果不合适,请尝试long,如果它不适合,请尝试long long,如果它也不适合那里,我们有未定义的行为。遵循最新标准的C或C ++编译器将尝试将其置于无符号类型中。
  • 在这种特定情况下,该数字不适合intlong,因此编译器决定使用long long作为文字的类型。
  • 然后在此文字上使用一元减号运算符,最后以数字-2147483648结尾。具有讽刺意味的是,这将适合带有二进制补码格式的有符号整数,但更改类型为时已晚,编译器已选择long long作为类型。

(1)如果您有无符号后缀,或者如果您有十六进制格式等,则此“内部表”看起来不同。如果存在无符号后缀,则仅检查该数字是否适合无符号数字。如果有十六进制表示法(但没有后缀),它将检查int,然后检查unsigned int,然后检查long等等。

答案 3 :(得分:0)

实际上我从CS:APP的pdf文件中找到了解释,它完美地给出了解决方案,你可以从这里下载。 http://www.csapp.cs.cmu.edu/public/waside/waside-tmin.pdf