int a = -534;
unsigned int b = (unsigned int)a;
printf("%d, %d", a, b);
输出为-534, -534
为什么类型转换没有发生?
我希望输出结果是-534, 534
如果我修改代码为
int a = -534;
unsigned int b = (unsigned int)a;
if(a < b)
printf("%d, %d", a, b);
它什么都没打印出来...毕竟 a
小于 b
吗?
int a = -534;
unsigned int b = (unsigned int)a;
printf("%d, %d", a, b);
输出为-534, -534
为什么类型转换没有发生?
我希望输出结果是-534, 534
如果我修改代码为
int a = -534;
unsigned int b = (unsigned int)a;
if(a < b)
printf("%d, %d", a, b);
它什么都没打印出来...毕竟 a
小于 b
吗?
因为您使用 %d
进行打印,应该使用 %u
来打印无符号数。由于 printf 是一个变参函数,它无法知道参数的类型,必须依靠格式说明符来确定参数类型。因此,您所做的类型转换没有效果。
%d
,无符号值被 printf()
通过 reinterpret_cast
转换回有符号值。%d
表示“将该值解释为有符号整数”。 - VladUINT_MAX+1
同余的最小正数。如果您使用32位无符号整数,那么-534将被转换为4294966762(在2s补码机器上,这具有与-534相同的比特表示)。 - cafreinterpret_cast
转换的。printf()
是C函数。它们只是被强制转换了。 - Chris Lutzreinterpret_cast
的操作,我只是指语义:二进制表示被解释为int,而不考虑参数的类型。在C++中(我们都熟悉),这种语义是通过reinterpret_cast
来表达的,而在C中,强制转换是不同语义的混合体(至少从C++的角度来看)。 - Vlad首先,你不需要进行强制类型转换:通过将a
赋值给b
,a
的值会被隐式转换为unsigned int
。因此,你的语句等价于:
unsigned int b = a;
unsigned
整数类型的一个重要属性是它们的值始终在范围[0,max]内,其中unsigned int
的max值为UINT_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);
signed char c = -1;
unsigned char uc = c;
假设机器上的char
(有符号或无符号)是8位。 那么c
和uc
将存储以下值和位模式:
+----+------+-----------+
| c | -1 | 11111110 |
+----+------+-----------+
| uc | 255 | 11111111 |
+----+------+-----------+
c
和uc
的位模式不同。编译器必须确保c
的值为-1
,而uc
的值为UCHAR_MAX
,在此计算机上为255。在printf中,你的格式说明符要求打印一个有符号整数,因此底层字节被解释为有符号整数。
你应该使用%u
来指定你想要一个无符号整数。
编辑:a==b
在比较时为true,这是奇怪的行为,但它是完全有效的。你没有改变底层位,只是要求编译器以某种方式处理底层位。因此,按位比较得到true。
[推测]
我会怀疑行为可能会因编译器实现而异 - 即,虚构的CPU可能不会对有符号和无符号数字使用相同的逻辑,因此按位比较将失败。[/推测]
a
和b
具有不同的位,a == b
也是成立的。请查看我的答案以获取详细信息。 - Alok SinghalC 有时可能会变得很丑陋。问题在于,-534 总是表示值 0xfffffdea,无论它存储在具有 unsigned int 或 signed int 类型的变量中。要比较这些变量,它们必须是相同类型的,因此一个将自动转换为 unsigned 或 signed int 以匹配另一个。一旦它们是相同类型,它们就相等,因为它们表示相同的值。
似乎函数 abs 提供了您想要的行为:
int a = -534;
int b = abs(a);
printf("%d, %d", a, b);
0xfffffdea
中的 f 数量可能会有所不同。例如,在 16 位机器上,它将只是 0xfdea
,而在 64 位机器上,您将有 13 个 f,后跟 dea
。 - MSalters我猜 Tronic 和 Hassan 已经足够回答为什么 b 被打印为-534的第一个情况了。你不应该使用 %d,而应该使用 %u。
至于你的第二个情况,由于存在隐式类型转换,a 和 b 将会相同,导致你的比较没有产生预期的结果。
关于第二个问题:
比较操作不能在两种不同类型之间进行 - 它们总是隐式转换为“最低公共分母”,在此情况下将是unsigned int
。这很恶心和反直觉,我知道。
a==b
为真。 - Hassan Syed将有符号整数类型从带符号转换为无符号并不会修改位模式,它只是改变了位模式的解释。
您还存在格式说明符不匹配的问题,应该使用%u来表示无符号整数,但即使这样,结果也不会像您预期的534那样,而是4294966762。
如果您想将负值变为正值,只需取反即可:
unsigned b = (unsigned)-a ;
printf("%d, %u", a, b);