当字节溢出时会发生什么?

说我们有

byte byte1 = 150; // 10010110  
byte byte2 = 199; // 11000111

如果我们现在做这个加法

byte byte3 = byte1 + byte2;

我认为我们最终会得到字节3 = 94,但实际发生了什么?我是否以某种方式覆盖了其他记忆,还是完全无害?

有帮助吗?

解决方案

这很简单。它只是进行了加法,并以超过8位的数字出现。第九位(是一个)只是“掉下来”,而您剩下的8位构成了数字94。

(是的,这是无害的)

其他提示

在C#中,如果您有

 checked { byte byte3 = byte1 + byte2; }

它将引发溢出异常。代码已编译 unchecked 默认。正如其他答案所说的那样,价值将“缠绕”。 IE, byte3 = (byte1 + byte2) & 0xFF;

顶部将被截断。它对任何其他记忆都不是有害的,仅在意想不到的结果方面有害。

进位旗被设定了...但是除了结果不是您的期望之外,也不会有不良影响。

通常(确切的行为将取决于语言和平台),结果将被模拟256。 IE 150+199 =349。349mod 256 = 93。

这不应影响任何其他存储。

由于您已经标记了问题C#,C ++和C,因此我会回答有关C和C ++的问题。在签名类型的C ++溢出中,包括 sbyte (我相信这是 signed char 在C/C ++中)导致不确定的行为。但是对于未签名类型,例如 byte (那是 unsigned char 在C ++中)结果是Modulo 2n 其中n是无符号类型中的位数。在c#中,第二个规则保留,如果签名类型在 checked 堵塞。我在C#部分中可能错了。

C#中的溢出是无害的 - 您不会溢出内存 - 您只需获得结果的最后8位即可。如果您希望这个例外,请使用“检查”的关键字。还要注意,您可能会发现字节+字节给出INT,因此您可能需要抛弃到字节。

行为取决于语言。

在C和C ++中,签名的溢出是未定义的,未签名的溢出具有您提到的行为(尽管没有 byte 类型)。

在C#中,您可以使用 checked 明确说明您要收到异常的关键字,如果有溢出和 unchecked 明确说您要忽略它的关键字。

领先点刚刚下降。

并且算术溢出发生。由于150+199 = 349,二进制1 0101 1101,上部1位被删除,字节变为0101 1101;即一个字节可以保持溢出的位数。

没有造成损害 - 例如 记忆 没有溢出到另一个位置。

让我们看一下实际发生的情况(在C中(假设您有适当的数据类型,有人指出C没有“字节”数据类型;尽管如此,可以添加8位数据类型)))))))))) 。如果这些字节在堆栈上声明,则它们存在于主内存中。在某个时候,字节将被复制到处理器进行操作(我正在跳过几个重要步骤,例如ProcessSor缓存...)。进入处理器后,它们将存储在注册表中;处理器将对这两个寄存器执行一个添加操作,以将数据添加在一起。 这是发生混乱的原因。 CPU将在本机(或有时,指定)数据类型中执行添加操作。假设CPU的本机类型是32位单词(并且该数据类型是用于添加操作的方法);这意味着这些字节将存储在32位单词中,上部24位不设置;添加操作的确将在目标32位单词中进行溢出。但是(这是重要的位)当数据从寄存器从寄存器复制到堆栈时,只有最低的8位(字节)将复制回目标变量在堆栈上的位置。 (请注意,字节包装和这里的堆栈也有一些复杂性。)

因此,这是结果;添加会导致溢出(取决于选择的特定处理器指令);但是,将数据从处理器中复制到适当尺寸的数据类型中,因此溢出是看不见的(并且假设编写正确的编译器,则无害)。

就c#而言,添加两个类型值 byte 一起产生类型的值 int 然后必须归还 byte.

因此,您的代码示例将导致编译器错误,而无需将字节放回以下内容。

byte byte1 = 150; // 10010110  
byte byte2 = 199; // 11000111

byte byte3 = (byte)(byte1 + byte2);

有关更多详细信息,请参见MSDN 关于这个。另外,请参阅 C#语言规范, ,第7.3.6节数字促销。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top