这里最重要的是,在 Arduino 中int 是 16 位类型。这将解释一切
对于uint32_t a = 0xFF << 8
: 0xFF 是类型int
1。结果 0xFF00 是 16 位 int 20xFF << 8
中的有符号负值。再次将值分配给变量时,向上转换时将符号扩展为3,因此结果变为0xFFFFFF00Uint
uint32_t
对于以下行
uint32_t b = 0xFF;
uint32_t c = b << 8;
0xFF在 16 位 int 中为正数b
,因此也包含 0xFF。然后将其左移 8 位结果为 0x0000FF00,因为b << 8
它是一个uint32_t
表达式。它比这里更广泛,int
所以这里没有促销int
活动
同样,uint32_t a = (unsigned)0xFF << 8
输出为 0x0000FF00,因为转换为正的 0xFFunsigned int
仍然是正的。向上转换unsigned int
到uint32_t
进行零扩展,但符号位已经为零,因此即使您这样做int32_t b = 0xFF; uint32_t c = b << 8
,高位仍然为零。与“奇怪” uint32_t a = 0x000000FF << 8
相同。而不是 (unsigned)0xFF 您可以使用完全相同的版本(但更短)0xFFU
OTOH,如果您将 b 声明为uint8_t b = 0xFF
or int8_t b = 0xFF
then 情况将有所不同,则会发生整数提升,结果将类似于第一行 (0xFFFFFF00U)。如果你投 0xFF 来signed char
喜欢这个
uint32_t b = (signed char)0xFF;
uint32_t c = b << 8;
然后在提升为 int 时,它将被符号扩展为 0xFFFF。类似地,将其转换为int32_t
或uint32_t
将导致从signed char
32 位宽值 0xFFFFFFFF的符号扩展
如果您改为unsigned char
like in uint32_t a = (unsigned char)0xFF << 8;
,则将(unsigned char)0xFF
使用零扩展名将4提升为 int ,因此结果将与uint32_t a = 0xFF << 8;
总结:如有疑问,请查阅标准。编译器很少对你说谎
1 默认情况下不是 int 的整数文字类型?
整数常量的类型是可以表示其值的对应列表中的第一个。
Suffix Decimal Constant Octal or Hexadecimal Constant
-------------------------------------------------------------------
none int int
long int unsigned int
long long int long int
unsigned long int
long long int
unsigned long long int
2严格来说,像这样转换为符号位是未定义的行为
3规则是加 UINT_MAX + 1
否则,如果新类型是无符号的,则在新类型可以表示的最大值的基础上重复加减一,直到该值在新类型的范围内。
4如果值适合目标类型,转换将始终保留输入值,因此将有符号类型转换为更广泛的有符号类型将通过符号扩展完成,将无符号类型转换为更广泛的类型将通过零扩展