C# 在内存中表示负整数并将其强制转换为未经检查的方式

The way C# represents negative integers in memory and casts them unchecked

C# 有多种值类型,每种都有自己的用途。 Int32 的范围从 -(0x7FFFFFFF + 1) 到 0x7FFFFFFF,并且从我曾经 运行 它的每台机器来看,似乎 unchecked((int)0xFFFFFFFF) 总是让我得到一个结果值 -1。总是这样吗?此外,.NET 在任何系统的内存中是否始终将 -1 表示为 0xFFFFFFFF?前导位总是符号位吗?它是否总是对整数使用二进制补码符号二进制表示?

System.Int32 的文档明确指出它以二进制补码形式存储。它在最底部:

In addition to working with individual integers as decimal values, you may want to perform bitwise operations with integer values, or work with the binary or hexadecimal representations of integer values. Int32 values are represented in 31 bits, with the thirty-second bit used as a sign bit. Positive values are represented by using sign-and-magnitude representation. Negative values are in two's complement representation. This is important to keep in mind when you perform bitwise operations on Int32 values or when you work with individual bits. In order to perform a numeric, Boolean, or comparison operation on any two non-decimal values, both values must use the same representation.

看来您所有问题的答案都是肯定的。

此外,Int32 的范围是从 -(0x80000000) 到 0x7FFFFFFFF。

C#——以及地球上几乎所有其他“计算机”——以 2 的补码表示整数。我相信在某一时刻,已经有 CPU 设计使用其他表示法,但是现在,您可以非常可靠地依赖于以 2 的补码表示法表示的整数。

  • 我们从右到左计算位,最右边的位,第 0 位是最低有效位,最左边的位是最高有效位。

  • 高位(最左边)位为符号:0为正; 1为负。

  • 其余位携带值。这意味着 N 位整数的有效域是 -(2n-1) <= x <= +(2n-1-1).也就是说,比起正数,可以表示多一个负数:对于16位有符号整数,定义域是-32,768到+32,767。

将数字放入二进制补码很容易:

  • 将其绝对值转换为 binary/base-2 表示法。
  • 如果值为负,
    • 反转位
    • 加 1

所以,值+1表示为0x0001,而-1表示为

  • 0x0001(二进制1的绝对值)
  • 0xFFFE(位反转)
  • 0xFFFF(加 1)

或 0xFFFF

使用二进制补码的原因是它使 CPU 设计更简单:因为减法是负数的加法(例如 3-2 与 3 + -2 相同),它们不需要必须设计减法电路:

  • 1-1 与 1 + -1 相同,计算结果为零。

  • 或十六进制,

      0x0001 (decimal +1)
    + 0xFFFF (decimal -1)
      ======
      0x0000 (decimal 0)
    

在大多数 CPU 中,进位进位或进位出高位设置定点溢出标志。