C语言用移位操作求各整型最大值时printf打印溢出问题求助
问题根因
你的代码存在三处核心错误,导致溢出问题:
- 运算符优先级错误:你对移位结果做强制类型转换,而C语言中强制类型转换优先级高于移位运算,移位操作执行时左操作数
1仍为默认的int类型,溢出发生在转换之前,转换的是已经出错的结果。 - 有符号数移位未定义:C标准明确规定,有符号整数左移时如果进位到符号位属于未定义行为,结果不受标准保障。
- 有符号最大值计算逻辑错误:有符号整型最高位为符号位,最大值为
2^(位宽-1) - 1,而非无符号类型的2^位宽 -1,你原始的移位位数计算适配的是无符号类型,不适用有符号整型。
问题1:如何正确打印计算结果
正确实现需要先将左操作数转换为对应目标类型的无符号版本,再执行移位计算,示例代码如下:
#include <stdio.h> int main() { printf("Greatest short: %d \n", (short)(((unsigned short)1 << (sizeof(short) * 8 - 1)) - 1)); printf("Greatest int: %i \n", (int)(((unsigned int)1 << (sizeof(int) * 8 - 1)) - 1)); printf("Greatest long int: %li \n", (long int)(((unsigned long int)1 << (sizeof(long int) * 8 - 1)) - 1)); printf("Greatest long long int: %lli \n", (long long int)(((unsigned long long int)1 << (sizeof(long long int) * 8 - 1)) - 1)); return 0; }
如果不需要自行实现计算逻辑,也可以直接使用标准库<limits.h>中已经定义好的宏,兼容性更高:
#include <stdio.h> #include <limits.h> int main() { printf("Greatest short: %d \n", SHRT_MAX); printf("Greatest int: %i \n", INT_MAX); printf("Greatest long int: %li \n", LONG_MAX); printf("Greatest long long int: %lli \n", LLONG_MAX); return 0; }
问题2:为什么较小类型强制转换为更大类型时数值会变化
你遇到的数值变化和强制转换本身无关,是因为你转换的对象是移位溢出后得到的错误值,而非正确的小类型值。
C标准明确规定,合法的小范围有符号整型转换为大范围有符号整型时,会自动做符号扩展,转换前后数值完全一致。你执行的强制转换操作本身没有问题,错误发生在转换之前的移位步骤。
内容的提问来源于stack exchange,提问作者user305883
相关产品推荐
相关产品推荐

