0u是否默认视为有符号整数?为何触发无符号-有符号比较警告?
为什么
uint16与0u比较会触发有符号/无符号警告? 问题的核心在于C语言的整数提升和寻常算术转换规则,具体拆解如下:
第一个触发警告的例子分析
先看这段代码的类型变化:
uint16 x = 5; if(((x) & (uint16)0x0001u) > 0u) {...}
- 左侧表达式
((x) & (uint16)0x0001u)的结果类型是uint16(即unsigned short)。 - 右侧的
0u是unsigned int类型(C标准规定,带u后缀的整数常量默认类型为unsigned int,除非数值超出其范围才会升级)。
根据C的整数提升规则:当unsigned short的取值范围(065535)完全被包含在`int`的取值范围(通常是-21474836482147483647)内时,编译器会将unsigned short提升为有符号的int,而非无符号类型。
此时比较的两边变成了:
- 左侧:提升后的
int(有符号) - 右侧:
unsigned int(无符号)
一个有符号类型和无符号类型直接比较,编译器就会触发“无符号与有符号比较”的警告。
第二个消除警告的例子分析
再看修改后的代码:
if(((x) & (uint16)0x0001u) > (uint8)0u) {...} //No warning
- 右侧的
(uint8)0u是unsigned char类型,它的取值范围(0~255)同样完全在int的范围内,所以会被提升为int(有符号)。 - 左侧的
uint16依然会被提升为int。
此时比较的两边都是int类型(均为有符号),类型匹配,因此不会触发警告。
补充说明
如果你的平台上int是16位(如今几乎不存在),unsigned short的最大值(65535)等于int的最大值,此时unsigned short会被提升为unsigned int,第一个例子就不会出现警告。但在主流的32位/64位平台上,int的宽度远大于uint16,就会出现你遇到的情况。
内容的提问来源于stack exchange,提问作者Johan
相关产品推荐
相关产品推荐

