为什么unsigned int 0xFFFFFFFF等于int -1?

在C或C ++中,size_t(一个unsigned int数据types)可以容纳的最大数量与向该数据types转换-1相同。 例如,请参阅size_t的无效值

为什么?

我的意思是,(谈论32位整数)AFAIK最高有效位将符号数据types(即位0x80000000形成一个负数)保存。 那么,1是0x00000001 .. 0x7FFFFFFFF是int数据types可以容纳的最大正数。

然后,AFAIK -1 int的二进制表示应该是0x80000001(也许我错了)。 为什么/如何将这个二进制值转换为任何完全不同的(0xFFFFFFFF)时,铸造整数为无符号? 或..如何可能形成一个二进制-1的0xFFFFFFFF?

我毫不怀疑在C:((unsigned int)-1)== 0xFFFFFFFF或((int)0xFFFFFFFF)== -1是等于1 + 1 == 2,我只是想知道为什么。

C和C ++可以在许多不同的体系结构和机器types上运行。 因此,他们可以有不同的数字表示:二的补码,而补码是最常见的。 一般来说,您不应该依赖程序中的特定表示。

对于无符号整数types( size_t是其中之一),C标准(我认为也是C ++标准)指定了精确的溢出规则。 简而言之,如果SIZE_MAX是typessize_t的最大值,则expression式

(size_t) (SIZE_MAX + 1)

保证为0 ,因此可以确定(size_t) -1等于SIZE_MAX 。 其他无符号types也是如此。

请注意,以上情况属实:

  • 对于所有的无符号types,
  • 即使底层机器不代表二进制补码中的数字 。 在这种情况下,编译器必须确保身份是真实的。

另外,上面的意思是你不能依赖于签名types的特定表示。

编辑 :为了回答一些评论:

假设我们有一个代码片段:

 int i = -1; long j = i; 

j中的赋值有一个types转换。 假设intlong具有不同的大小(大多数[所有?] 64位系统), ij内存位置的位模式将会不同,因为它们具有不同的大小。 编译器确保ij-1

同样的,当我们这样做时:

 size_t s = (size_t) -1 

有一个types转换正在进行。 -1inttypes的。 它有一个位模式,但是这个例子是不相关的,因为当转换到size_t由于转换发生时,编译器会根据types的规则(在这个例子中是size_t )来转换 。 因此,即使intsize_t具有不同的大小,该标准也保证了上面存储的值将是size_t可以采用的最大值。

如果我们这样做:

 long j = LONG_MAX; int i = j; 

如果LONG_MAX大于INT_MAX ,则i的值是实现定义的(C89,第3.2.1.2节)。

这叫做二补。 要做一个负数,反转所有的位,然后加1.所以要将1转换为-1,将其反转为0xFFFFFFFE,然后加1使得0xFFFFFFFF。

至于为什么这样做, 维基百科说:

二进制补码系统的优点是不需要加法和减法电路检查操作数的符号来决定是加还是减。 这个属性使得系统的实现更简单,并且能够容易地处理更高精度的算术。

你的第一个问题,关于为什么(unsigned)-1给出最大可能的无符号值,只是意外地与二进制补码有关。 原因-1转换为无符号types给出该types的最大可能值是因为标准说无符号types“遵循算术模2 n的定律,其中n是该特定大小的值表示中的位数整数。”

现在,对于2的补码,最大可能的无符号值和-1的表示恰好相同 – 但即使硬件使用另一种表示(例如1的补码或符号/幅度),将-1转换为无符号types也必须仍然产生该types的最大可能值。

两个补码是非常好做减法就像增加:)

     11111110(254或-2)
    +00000001(1)
    ---------
     11111111(255或-1)

     11111111(255或-1) 
    +00000001(1)
    ---------
    100000000(0 + 256)

这是二进制补码 。

主要的好处是,无论使用的是无符号还是带符号的int,都可以得到相同的编码。 如果你从0减1,整数简单地包装。 因此小于0的是0xFFFFFFFF。

因为int -1的位模式是hex无符号的FFFFFFFF。 11111111111111111111111111111111二进制无符号。 但在int中,第一位表示是否为负数。 但是在unsigned int中,第一位只是一个额外的数字,因为unsigned int不能是负数。 所以多余的位使得unsigned int能够存储更大的数字。 与unsigned int 11111111111111111111111111111111(二进制)或FFFFFFFF(hex)是一个uint可以存储的最大数字。 不推荐使用未签名的Ints,因为如果它们变为负值,则会溢出并达到最大值。

Interesting Posts