10

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

cout<<-2147483648 ;    //Output: 2147483648

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

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

那么,我的代码的以前版本有什么问题?不是int类型吗?或者整数的下限到底是多少?非常感谢。

4

4 回答 4

11

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

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

于 2012-09-27T11:57:13.923 回答
3

那么,我的代码的以前版本有什么问题?

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

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

不是int类型吗?

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

或者整数的下限到底是多少?

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

该语言没有指定整数类型的确切大小。只是它int必须至少有 16 位、long至少 32 位和(自 2011 年以来)long long至少 64 位。

于 2012-09-27T12:32:27.237 回答
2

首先,重要的是要了解没有负整数文字

其他人已经解释了为什么 OP 的特定编译器的行为如此。但为了记录,这是编译器在 32 位系统上应该做的,字里行间:

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

(1) 如果你有一个无符号后缀,或者你有十六进制格式等,这个“内部表”看起来会有所不同。如果有一个无符号后缀,它只会检查数字是否适合无符号数字。如果有十六进制表示法(但没有后缀),它将检查 int,然后是 unsigned int,然后是 long 等等。

于 2012-09-27T13:10:40.097 回答
0

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

于 2012-10-02T04:42:57.197 回答