未经检查的 int 溢出如何工作 C#
How unchecked int overflow work c#
我们知道一个int值的最大值是2^31 - 1,最小值是-2^31。如果我们将 int 设置为最大值:
int x = int.MaxValue;
我们取那个 x 并在未选中的字段中加一
unchecked
{
x++;
}
然后我们得到x = int的最小值。我的问题是为什么会发生这种情况以及它是如何以二进制形式发生的。
在 C# 中,内置整数由预定义长度的位值序列表示。对于长度为 32 位的基本 int 数据类型。由于 32 位只能表示 4,294,967,296 个不同的可能值(因为那是 2^32),
由于 int 可以容纳正数和负数,因此必须以某种方式对数字的符号进行编码。这是用第一位完成的。如果第一位是1,那么这个数就是负数。
以下是以十六进制和十进制形式排列在数字行上的 int 值:
Hexadecimal Decimal
----------- -----------
0x80000000 -2147483648
0x80000001 -2147483647
0x80000002 -2147483646
... ...
0xFFFFFFFE -2
0xFFFFFFFF -1
0x00000000 0
0x00000001 1
0x00000002 2
... ...
0x7FFFFFFE 2147483646
0x7FFFFFFF 2147483647
正如您从该图表中看到的,代表最小可能值的位是通过将最大可能值加一而得到的,同时忽略符号位的解释。当一个带符号的数字以这种方式相加时,它被称为"integer overflow"。是否允许整数溢出或将其视为错误可使用 C# 中的已检查和未检查语句进行配置。
This representation is called 2's complement
如果想更深入可以check this link
Int 的最大值为 2^31 - 1 因为,int 是 Int32
的别名,它在内存中存储 4 个字节来表示该值。
现在让我们来谈谈int.Max + 1
的概念。在这里你需要了解用于存储负值的Signed number representations。在二进制数表示中,没有什么像负数,但它们由一个补码和二进制补码位表示。
比方说,我的 int1 有一个 1 字节的存储内存,即。 8 位。因此,您可以存储到 int1
中的最大值是 2^8 -1 = 255
。现在让我们在这个值中加 1-
11111111
+ 00000000
----------
100000000
你的输出是十进制的100000000 = (512),这超出了int1的存储容量,代表十进制的-256的负值(因为第一位表示负值)。
这就是 int.Max 加 1 变成 int.Minimum 的原因。即
`int.Maximum + 1 = int.Minimum`
好的,为了方便起见,我假设 C# 中有一个 4 位整数类型。最高有效位用于存储符号,其余三位用于存储幅度。
在这种表示中可以存储的最大数字是 +7(以 10 为基数的正 7)。在二进制中,这是:
0111
现在让我们添加正数:
0111
+0001
_____
1000
哎呀,这从量级转移过来并翻转了符号位!您在上面看到的总和实际上是数字 -8,这是可以存储在此表示中的最小可能数字。如果您不熟悉 two's complement, which is how signed numbers are commonly represented in binary, you might think that number is negative zero (which would be the case in a sign and magnitude 表示法)。您可以阅读二进制补码以更好地理解这一点。
我们知道一个int值的最大值是2^31 - 1,最小值是-2^31。如果我们将 int 设置为最大值:
int x = int.MaxValue;
我们取那个 x 并在未选中的字段中加一
unchecked
{
x++;
}
然后我们得到x = int的最小值。我的问题是为什么会发生这种情况以及它是如何以二进制形式发生的。
在 C# 中,内置整数由预定义长度的位值序列表示。对于长度为 32 位的基本 int 数据类型。由于 32 位只能表示 4,294,967,296 个不同的可能值(因为那是 2^32),
由于 int 可以容纳正数和负数,因此必须以某种方式对数字的符号进行编码。这是用第一位完成的。如果第一位是1,那么这个数就是负数。
以下是以十六进制和十进制形式排列在数字行上的 int 值:
Hexadecimal Decimal
----------- -----------
0x80000000 -2147483648
0x80000001 -2147483647
0x80000002 -2147483646
... ...
0xFFFFFFFE -2
0xFFFFFFFF -1
0x00000000 0
0x00000001 1
0x00000002 2
... ...
0x7FFFFFFE 2147483646
0x7FFFFFFF 2147483647
正如您从该图表中看到的,代表最小可能值的位是通过将最大可能值加一而得到的,同时忽略符号位的解释。当一个带符号的数字以这种方式相加时,它被称为"integer overflow"。是否允许整数溢出或将其视为错误可使用 C# 中的已检查和未检查语句进行配置。
This representation is called 2's complement
如果想更深入可以check this link
Int 的最大值为 2^31 - 1 因为,int 是 Int32
的别名,它在内存中存储 4 个字节来表示该值。
现在让我们来谈谈int.Max + 1
的概念。在这里你需要了解用于存储负值的Signed number representations。在二进制数表示中,没有什么像负数,但它们由一个补码和二进制补码位表示。
比方说,我的 int1 有一个 1 字节的存储内存,即。 8 位。因此,您可以存储到 int1
中的最大值是 2^8 -1 = 255
。现在让我们在这个值中加 1-
11111111
+ 00000000
----------
100000000
你的输出是十进制的100000000 = (512),这超出了int1的存储容量,代表十进制的-256的负值(因为第一位表示负值)。
这就是 int.Max 加 1 变成 int.Minimum 的原因。即
`int.Maximum + 1 = int.Minimum`
好的,为了方便起见,我假设 C# 中有一个 4 位整数类型。最高有效位用于存储符号,其余三位用于存储幅度。
在这种表示中可以存储的最大数字是 +7(以 10 为基数的正 7)。在二进制中,这是:
0111
现在让我们添加正数:
0111
+0001
_____
1000
哎呀,这从量级转移过来并翻转了符号位!您在上面看到的总和实际上是数字 -8,这是可以存储在此表示中的最小可能数字。如果您不熟悉 two's complement, which is how signed numbers are commonly represented in binary, you might think that number is negative zero (which would be the case in a sign and magnitude 表示法)。您可以阅读二进制补码以更好地理解这一点。