在C语言中,没有后缀的整数常量默认会尝试匹配 int 类型。但如果该值太大,在 int 类型中放不下,编译器会根据一套规则自动为常量选择能容纳该值的第一个合适类型。
类型推导规则
编译器根据值是否有后缀以及是十进制还是八/十六进制来决定类型:
- 无后缀常量:
- 十进制:依次尝试
int->long->long long。 - 八/十六进制:依次尝试
int->unsigned int->long->unsigned long->long long->unsigned long long(八/十六进制可优先匹配无符号类型)。
- 十进制:依次尝试
- 带后缀常量:根据后缀(如
U、L、UL、LL、ULL)在对应的有符号/无符号、长度序列中匹配。
类型匹配顺序表(对应图表)
| 后缀 | 十进制常量匹配顺序 | 八或十六进制常量匹配顺序 |
|---|---|---|
| 无 | 1. int2. long3. long long | 1. int2. unsigned int3. long4. unsigned long5. long long6. unsigned long long |
| U | 1. unsigned int2. unsigned long3. unsigned long long | 1. unsigned int2. unsigned long3. unsigned long long |
| L | 1. long2. long long | 1. long2. unsigned long3. long long4. unsigned long long |
| UL | 1. unsigned long2. unsigned long long | 1. unsigned long2. unsigned long long |
| LL | 1. long long | 1. long long2. unsigned long long |
| ULL | 1. unsigned long long | 1. unsigned long long |
规则解析与示例
- 编译器选择能容纳该值的第一个类型(按表中数字序号依次尝试)。
- 例如:后缀为
U的十六进制常量0xFFU,先尝试unsigned int;若值过大放不下,则采用unsigned long。 - 若数值极大(如
9460730472580800),可能最终采用unsigned long long。 - 如果所有类型都放不下,编译器会报错提示溢出。
补充
- 八/十六进制的特殊性:八进制和十六进制常量在没有后缀时,会优先尝试无符号类型(
unsigned int等),而十进制默认只尝试有符号类型。这在赋值给无符号变量时很自然,但混合运算时需注意隐式转换。 - 后缀大小写等效:
u与U、l与L、ll与LL等效,但强烈建议用大写(如ULL)避免小写l与数字1混淆。 - 溢出截断风险:若强行用较小类型接收大常量(如
int x = 9999999999;),会发生截断或警告;建议对大数显式加后缀(如9999999999LL)以匹配变量类型。 - 实际开发建议:为防歧义,声明变量和常量时尽量类型一致(如
unsigned long x = 100UL;),并用正确格式符输出(%llu配unsigned long long)。