为什么INT_MAX减INT_MIN等于 -1
Why INT_MAX minus INT_MIN equals -1?
正如此页面所建议的,INT_MAX = 32767
和INT_MIN = -32767
,因此INT_MAX - INT_MIN
应该等于65534,但是它给了我-1;
我很困惑,因为 65534 不会在 C++ 中溢出 int 的限制,即使我在长整型中分配值,它仍然给了我 -1。我想可能是我误解了关于C++减少的一些机制。有人不知道INT_MAX
减去INT_MIN
时到底发生了什么?提前感谢!
INT_MAX
仅在int
类型实际上是 16 位宽的编译器上时才等于 32767。如今,在嵌入式处理器的编译器中仍然可以看到这样的INT_MAX
值。
无论INT_MAX
是什么,它既是 int
类型的值,也是该类型的最大值。如果在int
类型中,从最正的值中减去最负的int
值,则会触发溢出,这是未定义的行为。
无论您的int
是16位宽还是64位,都没有关系;根据ISO C,INT_MAX - INT_MIN
表示的计算没有明确定义的含义。
-1 结果可能由您的实现定义。 也就是说,编译器遵守有关整数溢出的特定规则。查看您的编译器手册。
如果类型比 int
宽,则可以执行减法。例如,假设long long
比某个给定编译器上的int
宽。(这不是必需的,但假设我们有一个实现,这是真的,这很常见(。然后我们可以做:
(long long) INT_MAX - (long long) INT_MIN
现在没有溢出,因为计算是在更广泛的类型中执行的。我们得到算术上正确的值。当然,该值不适合类型 int
。
现在关于 -1 的假设,请记住它可能只是一个侥幸,根本不是由编译器定义的。
假设您有一个用于二进制补码机的编译器,该编译器将签名溢出的行为定义为具有简单的"包装"语义。然后,-1 值可以解释如下。假设INT_MIN
是最负的二进制补码值,以二进制表示1000..0000
。 INT_MAX
是0111..1111
.然后计算INT_MAX - INT_MIN
减去这两个。 在较低的位中没有太多有趣的事情发生,因为0
序列正在从1
序列中减去。然后,减法达到上位:0 - 1
。 这导致值1
,借出("借"是减法与加法的"进位"对应的(。借款被丢弃,我们只剩下截断的结果1111...1111
. 这当然是两者的补码表示 -1。
注意INT_MIN
也可以简单地定义为-INT_MAX
,这是二进制值1000...0001
。在这种情况下,相同的包装算法将产生结果 -2,也许比 -1 更令人惊讶。
所以为什么你看到 -1 可能是你得到了 2 的补码包装行为,再加上 INT_MIN
实际上并不是 INT_MAX
的算术逆(这将需要 -2 结果(,而是一个比这少 1 的值。
如果你说INT_MAX = 32767
某些实现,当然甚至是32768溢出。
除了请注意,如果您要添加两个整数文字,即使您将该结果分配给long
,也要说int + int
(假设long可以保存该添加的结果(,这无济于事,因为当int
添加int
时可能会发生溢出 - 因为添加的结果不适合int
;在这种情况下,编译器不会将int
提升为long
,基于以下事实加法的结果不适合int
.
INT_MAX = 32767且 INT_MIN = -32767
实际上它们是:
-32767 (-2^15+1( 或更少*
32767 (2^15-1( 或更高版本*
我几乎在你的系统上,sizeof(int(==4 -> 4 字节 -> 32 位。
INT_MAX定义为 2^32-1 == 4294967295。
对INT_MIN应用相同。
键入 smth,例如:
std::cout << INT_MAX << " " << INT_MIN << std::endl;
你会看到的。int(INT_MAX-INT_MIN 中实际上有一个溢出,所以它是 -1。
该页面没有说任何此类内容。它说INT_MAX
至少是32767。它并没有说它是平等的。如果您想知道特定实现的实际价值,请将其打印出来(或查看该实现的文档,请记住它可能取决于目标体系结构(。
反正INT_MAX
的定义是int
的最大值,所以INT_MAX+1
就足以溢出int
的极限了,别说INT_MAX - INT_MIN
了。您获得的-1
值是特定于实现的行为,但这不是典型 2 补码实现的意外结果,其中 INT_MAX
等于 2N-1-1,INT_MIN
等于 -2N-1,对于某些值 N,称为以位为单位的int
的"宽度"。这是最常见的[*] 32,但标准允许低至16。因此,对于具有 32 位 2 补码int
的实现,实际值是2147483647
和-2147483648
的,对于具有 16 位 2 补码int
的实现,实际值是32767
和-32768
的
在这样的实现中,假设整数溢出环绕,那么INT_MAX - INT_MIN
的结果将如您所见-1
,因为数学值为 2 N-1,即 -1 模 2N。例如,GCC 有一个选项-fwrapv
如果你想确保整数溢出换行,你可以使用它,如果你不指定该选项,那么它可能会换行,或者它可能会做一些不同的事情。
[*] 通过一些非常不科学的"最常见"概念。
- 为什么在全局范围内使用"extern int a"似乎不行?
- int(c) 和 c-'0' 之间的区别。C++
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 为什么野牛仍在使用"int yylex(void)",却找不到"int yylex(YYS
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 是否可以从int转换为enum类类型
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- 'short int'持有的值溢出,但"自动"不会溢出?
- C 双重不能等于两个INT分裂
- 有没有办法检查int是否不等于数组中的所有值?(C )
- 在字符串中设置一个等于 int + "," 的某个字母
- 对于正值,int(doubleValue)是否保证小于或等于doubleValue
- 如果我将 int 设置为等于 2 个最大整数的总和会发生什么
- 如何重载赋值运算符以允许我的类等于基元类型,例如'int'
- sizeof(int)是否始终等于sizeof(void*)
- 设置一个字节等于int和cout
- 为什么 boost::is_same<int const&, boost::add_const<int &>::value 等于 false?
- 长类型Max等于int Max error + math.h pow()编译警告:隐式常量转换溢出