C(输出)中的无符号和有符号值

时间:2010-09-08 14:26:28

标签: c unsigned signed

signed int x = -5;
unsigned int y = x;

y的价值是多少?这是怎么回事?

5 个答案:

答案 0 :(得分:17)

取决于unsigned int的最大值。通常,unsigned int长度为32位,因此UINT_MAX为2 32 - 1. C标准(§6.3.1.3/ 2)要求签名→无符号转换为

  

否则,如果新类型是无符号的,则通过重复地添加或减去一个可以在新类型中表示的最大值来转换该值,直到该值在新类型的范围内。

因此y = x +((2 32 -1)+ 1)= 2 32 - 5 = 4294967291。


在当前大多数实现 2's complement平台中,y也与x的2的补码表示相同。

-5 = ~5 + 1 = 0xFFFFFFFA + 1 = 0xFFFFFFFB = 4294967291。

答案 1 :(得分:4)

来自C99标准:

  

6.3.1.3有符号和无符号整数

     
      
  1. 当整数类型的值转换为另一个整数类型时   除了_Bool,如果   该值可以用新类型表示,不变。
  2.   
  3. 否则,如果新类型是无符号的,则转换为   反复添加或   减去一个可以表示的最大值   在新型   直到该值在新类型的范围内。   49)
  4.         

    49)规则描述了数学值的算术,而不是给定类型表达式的值。

因此,您将有效地查看y = x + UINT_MAX + 1

这恰好意味着二进制补码表示不作为无符号整数使用,这使得它在大多数现代计算机上都非常快,因为它们对有符号整数使用二进制补码。

答案 2 :(得分:3)

y的值为UINT_MAX - 5 + 1,即UINT_MAX - 4

当您将有符号整数值转换为无符号类型时,该值将以2 ^ N为模减少,其中N是无符号类型中的值形成位数。这适用于负符号和正符号值。

如果您要从签名类型转换为相同大小的无符号类型,则上述意味着正签名值保持不变(例如+5转换为5)并添加负值到MAX + 1,其中MAX是无符号类型的最大值(-5转换为MAX + 1 - 5)。

答案 3 :(得分:1)

有符号值通常存储为two's complement

  

二进制补码是将负数编码为普通二进制数的一种方法,这样加法仍然有效。添加-1 + 1应该等于0,但普通加法给出2或-2的结果,除非操作特别注意符号位并执行减法。如果没有这个额外的步骤,则二进制补码得到正确的总和。

这意味着数字-5和4294967291在内存中的实际表示(对于32位字)是相同的,例如:0xFFFFFFFB0b11111111111111111111111111111011。所以当你这样做时:

unsigned int y = x;

x的内容逐字复制,即按位复制到y。这意味着如果您检查内存中xy的原始值,它们将是相同的。但是如果你这样做:

unsigned long long y1 = x;

x的值将在转换为无符号long long之前进行符号扩展。在长long为64位的常见情况下,这意味着y1等于0xFFFFFFFFFFFFFFFB

重要的是要注意投射到更大类型时会发生什么。将转换为更大的签名值的签名值将进行符号扩展。如果源值是无符号的,则不会发生这种情况,例如:

unsigned int z = y + 5;
long long z1 = (long long)x + 5; // sign extended since x is signed
long long z2 = (long long)y + 5; // not sign extended since y is unsigned

zz1将等于0,但z2则不会。这可以通过在扩展它之前将值转换为已签名的来解决:

long long z3 = (long long)(signed int)y + 5;

或类似地,如果希望发生符号扩展:

long long z4 = (long long)(unsigned int)x;

答案 4 :(得分:-1)

Y = 0xfffffffb 它是-5(二进制补码)的二进制表示