类型转换为C中的unsigned

Laz*_*zer 12 c c++ casting

int a = -534;
unsigned int b = (unsigned int)a;
printf("%d, %d", a, b);
Run Code Online (Sandbox Code Playgroud)

版画 -534, -534

为什么没有发生类型转换?

我期待它 -534, 534


如果我修改代码

int a = -534;
unsigned int b = (unsigned int)a;
if(a < b)
  printf("%d, %d", a, b);
Run Code Online (Sandbox Code Playgroud)

它不打印任何东西......毕竟a不到b

Tro*_*nic 15

因为你%d用于打印.使用%u无符号.由于printf是一个vararg函数,它不能知道参数的类型,而必须依赖于格式说明符.因此,你所做的类型转换没有效果.

  • 将负值转换为"unsigned int"值并不会否定它(将-534更改为534),它会将其转换为与原始模"UINT_MAX + 1"一致的最小正数.如果你有32位`unsigned int`s,-534将转换为4294966762(在2s补码机器上,它具有与-534相同的按位表示). (3认同)
  • 实际上,由于`%d`,无符号值由`printf()`得到`reinterpret_cast`-ed _back_.`%d`表示"获取值并将其解释为signed int" (2认同)

Alo*_*hal 5

首先,您不需要a强制转换:将的值隐式转换为unsigned int,并将其分配给b。因此,您的陈述等同于:

unsigned int b = a;
Run Code Online (Sandbox Code Playgroud)

现在,unsignedC和C ++ 中整数类型的一个重要属性是它们的值始终在[0,max ] 范围内,其中max for unsigned intUINT_MAX(在中定义limits.h)。如果您分配的值不在该范围内,则会将其转换为该范围。因此,如果值是负数,则UINT_MAX+1重复添加以使其在[0,UINT_MAX] 范围内。对于上面的代码,就好像我们写了:unsigned int b = (UINT_MAX + a) + 1。这不等于-a(534)。

请注意,无论基础表示形式是二进制补码,二进制补码还是符号幅度(或任何其他奇异编码),以上都是正确的。可以看到类似的内容:

signed char c = -1;
unsigned int u = c;
printf("%u\n", u);
assert(u == UINT_MAX);
Run Code Online (Sandbox Code Playgroud)

在典型的带有4字节的二进制补码机上intcis 0xffuis 0xffffffff。编译器必须确保在将值-1分配给u时将其转换为等于的值UINT_MAX

现在回到您的代码,printf格式字符串对于是错误的b。您应该使用%u。完成后,您会发现它显示的值UINT_MAX - 534 + 1不是534

当用于比较运算符时<,由于bis unsigned inta也将转换为unsigned int。给出b = a:更早的意思a < b是错误的:a因为unsigned int等于b

假设您有一台补码机,并且这样做:

signed char c = -1;
unsigned char uc = c;
Run Code Online (Sandbox Code Playgroud)

假设char该机器上的(有符号或无符号)是8位。然后cuc将存储以下值和位模式:

+----+------+-----------+
| c  |  -1  | 11111110  |
+----+------+-----------+
| uc | 255  | 11111111  |
+----+------+-----------+
Run Code Online (Sandbox Code Playgroud)

需要注意的是的位模式cuc是不一样的。编译器必须确保在计算机上c具有的值-1uc的值UCHAR_MAX255。

关于SO的问题我的答案有更多详细信息。