为什么 -2147483648 和 (int)-2147483648 之间不同

Why it is different between -2147483648 and (int)-2147483648

本文关键字:-2147483648 之间 int 为什么      更新时间:2023-10-16

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

cout<<-2147483648 ;    //Output: 2147483648

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

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

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

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

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

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

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

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

它不是 int 类型吗?

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

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

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

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

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

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

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

(1)如果您有无符号后缀,或者如果您有十六进制格式等,则此"内部表"看起来会有所不同。如果有无符号后缀,它只会检查该数字是否适合无符号数字。如果有十六进制表示法(但没有后缀),它将检查 int,然后检查无符号 int,然后检查 long,依此类推。

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