请参阅下面的代码。我感到困惑,为什么我需要先将变量var_u16
强制转换为int16_t,然后再强制转换为int32_t才能正确解释为MyFunc()中的带符号int。
我会认为,由于var_u16
具有最高有效位,因此,当简单地转换为int32_t时,编译器会理解这是一个负值。
相反,它仍然被解释为无符号值。为什么首先需要中间转换为int16_t?
我正在使用gcc 8.3.0
#include <stdio.h>
void MyFunc(int32_t s32Var)
{
printf("%d\n", s32Var);
}
int main()
{
uint16_t var_u16 = 0x8000;
MyFunc((int32_t)var_u16); // prints 32768
MyFunc((int32_t)(int16_t)var_u16); // prints -32768
return 0;
}
这里发生的是value正在从无符号的16位数字转换为有符号的32位数字。底层representation不相关。
由于任何可以存储在uint16_t
中的值也可以存储在int32_t
中,因此在转换为新类型时,该值保持不变。因此,值为[32768]的uint16_t
变为值为[32768]的int32_t
。
由于中间值32768无法存储为该类型,因此中间转换为int16_t
时会发生变化,因此该值将实现实现定义的转换,从而导致类型为int16_t
的表达式具有值-32768。
在第一种情况下,该值保持不变。发生这种情况是因为int32_t
可以代表uint16_t
的所有值。强制转换时,保留0x8000
值,只是将其填充为零。
编译器会理解这是一个负值
这是不正确的。如果两种表示形式,0x8000
是一个完全有效的正数。
int16_t
不能保存uint16_t
的所有值,并且0x8000
是这些值之一。相反,通过模块化算术,32768
变为-32768
。强制转换为int32_t
时,请对int16_t
进行符号扩展,并保持-32768
。
int32_t
类型的对象可以存储uint16_t
类型的值。
[当例如int16_t
的有符号整数类型的对象转换为例如int32_t
的较大的整数类型时,如果该对象的值为负,则其符号位将传播到较大的整数整数类型。