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

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

4

5 回答 5

17

这取决于 的最大值unsigned int。通常,aunsigned int是 32 位长,因此UINT_MAX是 2 32 - 1。C 标准(第 6.3.1.3/2 节)要求执行有符号 → 无符号转换

否则,如果新类型是无符号的,则通过在新类型中可以表示的最大值的基础上反复加减一,直到该值在新类型的范围内。

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


在当今大多数实现2 的补码平台中,也与 .的 2 的补码表示相同。yx

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

于 2010-09-08T14:33:31.877 回答
4

来自 C99 标准:

6.3.1.3 有符号和无符号整数

  1. 当整数类型的值转换为_Bool以外的其他整数类型时,如果该值可以用新类型表示,则保持不变。
  2. 否则,如果新类型是无符号的,则通过在新类型中可以表示的最大值的基础上反复加减一,直到该值在新类型的范围内。49)

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

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

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

于 2010-09-08T14:34:07.380 回答
3

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

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

如果要从有符号类型转换为相同大小的无符号类型,则上述表示正符号值保持不变(例如转换+5为转换为)。5MAX + 1MAX-5MAX + 1 - 5

于 2010-09-08T14:33:36.740 回答
2

有符号值通常存储为所谓的二进制补码

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

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

unsigned int y = x;

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

unsigned long long y1 = x;

的值x将在转换为 unsigned long 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;
于 2010-09-08T15:02:28.693 回答
-1

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

于 2010-09-08T14:28:17.847 回答