我在 c11 / N1570 6.3.1.8中找到这一行 - 通常的算术转换:
否则,如果带有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则具有无符号整数类型的操作数将转换为带有符号整数的操作数的类型类型。
然后我做了这样的测试
uint8_t ui8 = 0xFF;
int16_t i16 = 255;
if(i16 == ui8)
printf("%#.8X\n", i16);
根据我(明显)错误的推断i16 == ui8
,ui8
被隐式转换为int8_t
(根据上面引用的规则)。转化后ui8
等于-1
,因此if
必须“展开”为类似的内容;
if(i16 == (int8_t)ui8)
或
if(255 == -1)
这不是真的。 困扰我的是,在我运行代码后,条件似乎是真的。 你能帮助我理解上面引用中我错过了什么吗?
答案 0 :(得分:3)
在这种情况下,签名操作数i16
的类型为int16t
。比较完成后,它在无符号值和有符号值之间。由于签名类型int16t
能够保留uint8t
的所有可能值,因此uint8t
值可以转换为int16t
。因此FF
隐式转换为255
,而不是-1
。这使条件成立。
来自哈比森和斯蒂尔的C: A Reference Manual
5e,p。 190:
从一种整数类型转换为另一种整数类型的一般规则是,如果可能,结果的数学值应等于原始数学值。例如,如果无符号整数的值为15,并且此值将转换为有符号类型,则生成的有符号值也应为15。
答案 1 :(得分:3)
你必须了解这里发生的事情。当你声明:
uint8_t ui8 = 0xFF;
int16_t i16 = 255;
ui8
和i16
都设置了第一个8位。在这两种情况下,它们的值都是255
。您可以轻松地检查这是无符号8位值的最大值:
char - signed : -128 to 127
char - unsigned : 0 to 255
问题出现在这里:
if(i16 == (int8_t)ui8)
当ui8
被提升为int16_t
时,会出现符号扩展(这会扩展ui8
中最左边的位,将其复制到位8-15在转换过程中,这会使int16_t
ui8
的{{1}}表示为负值,导致上述比较成功(但出于错误的原因)。混合签名时必须非常小心/因此,无符号值。