如何处理溢出情况?

How are Overflow situations dealt with?

我只是想知道,谁负责处理计算机中的数学溢出情况?

例如,在下面的 C++ 代码中:

short x = 32768;
std::cout << x;

在我的机器上编译和运行这段代码给了我-32767

的结果

A "short" 变量的大小是 2 个字节 .. 我们知道 2 个字节可以容纳最大十进制值 32767(如果有符号).. 所以当我将 32768 分配给 x .. 在超过它的最大值之后值 32767 .. 它从 -32767 开始重新计数到 32767 等等 .. 到底发生了什么,所以在这种情况下给出了值 -32767 ? IE。在后台完成的二进制计算是什么导致这个值?

那么,是谁决定发生这种情况的?我的意思是谁负责决定当我的程序中发生数学溢出时..变量的值只是从它的最小值重新开始,或者抛出异常,或者程序只是冻结..等等?

是语言标准、编译器、我的OS、我的CPU,还是它是谁? 它如何处理这种溢出情况? (简单的解释或 link 的详细解释将不胜感激 :) )

顺便说一句,请问 .. 此外,谁来决定 'short int' 在我的机器上的大小?它也是语言标准、编译器、OS、CPU .. 等吗?

提前致谢! :)

编辑: 好的,所以我从这里了解到:Why is unsigned integer overflow defined behavior but signed integer overflow isn't?

是处理器定义了在溢出情况下会发生什么(例如在我的机器中它再次从 -32767 开始),这取决于处理器的 "representations for signed values",即。它是符号幅度,一个的补码还是二进制的补码...

是吗? 在我的例子中(当给出的结果就像再次从最小值 -32767 开始时......你怎么认为我的 CPU 代表带符号的值,以及值 -32767 是如何出现的(再次, 导致这个的二进制计算,请 :) ? )

它本身并不是从最小值开始的。它只是 t运行 计算其值,因此对于 4 位数字,您可以计数到 1111(二进制,= 15 十进制)。如果你递增一个,你会得到 10000,但是没有空间容纳它,所以第一个数字被删除,0000 仍然存在。如果你计算 1111 + 10,你会得到 1.

您可以像在纸上一样将它们相加:

  1111
  0010
  ---- +
 10001

但是处理器不会将整个数字加起来,而是只会加起来直到达到(在本例中)4 位。之后就没有空间可以再累加了,但是如果还有1到'carry',它就设置了溢出寄存器,所以你可以看看它最后一次相加是否溢出了。

处理器具有将数字相加的基本指令,并且它们具有用于较小和较大值的指令。 64 位处理器可以将 64 位数字相加(实际上,通常它们不会将两个数字相加,而是实际上将第二个数字添加到第一个数字,修改第一个数字,但这对故事来说并不重要)。

但是除了64位,他们往往还可以把32位、16位和8位的数相加。这部分是因为如果不需要更多,只加 8 位可能会很有效,但有时也可以向后兼容以前版本处理器的旧程序,这些程序最多可以加 32 位,但不能加 64 位。

这样的程序是用一条指令将32位的数相加,同样的指令在64位处理器上也一定存在,如果出现溢出行为也是一样的,否则程序无法运行运行 在较新的处理器上正确。

除了用处理器的核心结构加起来,还可以用软件加起来。您可以制作一个 inc 函数,将一大块位视为单个值。要递增它,您可以让处理器递增前 64 位。结果存储在块的第一部分。如果在处理器中设置了溢出标志,您将获取接下来的 64 位并将它们也递增。这样,您可以扩展处理器的限制以处理来自软件的大量数字。

处理溢出的方式也是如此。处理器只是设置标志。您的应用程序可以决定是否对其采取行动。如果你想要一个只增加到 65535 然后返回到 0 的计数器,你(你的程序)不需要对标志做任何事情。