为什么INT_MAX减去INT_MIN等于-1?

时间:2016-03-31 19:47:04

标签: c++

正如this page建议的那样,INT_MAX = 32767INT_MIN = -32767所以INT_MAX - INT_MIN应该等于65534,但它会给我-1;

我很困惑因为65534没有超出C ++中int的限制,即使我在long long int中赋值,它仍然给了我-1。我想可能是我误解了一些关于C ++减少的机制。任何人都没有INT_MAX减去INT_MIN时的确切情况?提前谢谢!

4 个答案:

答案 0 :(得分:7)

如果您使用INT_MAX类型实际为16位宽的编译器,则

int仅等于32767。现在,嵌入式处理器的编译器仍然可以看到INT_MAX的这样的值。

无论INT_MAX是什么,它都是int类型的,它是该类型的最大值。如果在int类型中,您从最积极的值中减去最负的int值,则会触发溢出,即未定义的行为

int是16位宽还是64位并不重要; INT_MAX - INT_MIN表示的计算根据ISO C没有明确定义的含义。

-1结果可能是由您的实现定义的。即您的编译器遵守有关整数溢出的特定规则。检查编译器手册。

如果可用的类型比int宽,则可以执行减法。例如,假设long long在某些给定编译器上比int宽。 (这不是必需的,但假设我们有一个实现,它是真的,这是常见的)。然后我们可以做到:

(long long) INT_MAX - (long long) INT_MIN

现在没有溢出因为计算是在更宽的类型中进行的。我们获得算术上正确的值。当然,该值不适合类型int

现在有一个关于-1的假设,请记住它可能只是一个侥幸,而根本没有你的编译器定义。

假设您有一个二进制补码机器的编译器,它将带符号溢出的行为定义为具有简单的“换行”语义。然后可以如下解释-1值。假设INT_MIN是最负的二进制补码值,由二进制的1000..0000表示。 INT_MAX0111..1111。计算INT_MAX - INT_MIN然后减去这两个。低位中没有太多有趣的事情,因为0的序列正从1的序列中减去。然后,减法到达高位:0 - 1。这导致值1,借用(“借用”是减法与加法“进位”的对应)。借用被丢弃,我们只剩下截断的结果1111...1111。那当然是-1的二进制补码表示。

请注意,INT_MIN也可以简单地定义为-INT_MAX,即二进制值1000...0001。在这种情况下,相同的包装算法将产生结果-2,可能比-1更令人惊讶。

那么为什么你看到-1可能就是你得到了两个补码包装行为,加上INT_MIN实际上并不是INT_MAX的算术逆的事实(这会要求一个-2结果),但是比这个值小1的值。

答案 1 :(得分:2)

如果你对某些实现说INT_MAX = 32767,当然甚至会有32768溢出。

除了注意,如果你要添加两个整数文字说int + int,即使你将结果分配给long(假设long可以保存该添加的结果),那也没有用,因为溢出使用int添加int时可能会发生 - 因为添加的结果不适合int;在这种情况下,编译器不会将int提升为long,因为添加结果不适合int内部。

答案 2 :(得分:1)

  

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

答案 3 :(得分:1)

该页面没有说明这种情况。它说INT_MAX至少是32767.它并不是说它是平等的。如果您想知道特定实现的实际价值,请将其打印出来(或者查看该实现的文档,记住它可能取决于目标架构)。

无论如何,INT_MAX的定义是int的最大值,因此INT_MAX+1足以超出int的限制,更不用说INT_MAX - INT_MIN 。您获得的-1的值是特定于实现的行为,但它不是来自典型的2补码实现的意外结果,其中{{1}等于2 N-1 -1且INT_MAX等于-2 N-1 ,对于某些值N,称为&#34;宽度&#34;以INT_MIN为单位。这通常是[*] 32,但标准允许低至16.因此对于具有32位2的实现,实际值为int2147483647对于具有16位2的补码-2147483648的实现,补int32767-32768

在这样的实现上,假设整数溢出包围,那么int的结果将是INT_MAX - INT_MIN,因为数学值为2 < sup> N -1,其为-1模2 N 。例如,如果您想确保整数溢出包装,GCC有一个选项-1,如果您没有指定该选项,那么它可能会换行,或者它可能会做一些不同的事情。

[*]通过一些非常不科学的概念&#34;最常见的&#34;。