Linux下GCC编译long int算术运算异常问题咨询
问题解析:整数常量类型与溢出导致的不符合预期输出
这是典型的整数常量类型推导和有符号整数溢出问题,咱们结合你的环境一步步拆解:
首先明确你的环境参数:
- Linux x86_64系统下,
int是4字节(32位有符号),范围为INT_MIN=-2147483648到INT_MAX=2147483647 long int是8字节(64位有符号),范围远大于int- g++ 4.8.5遵循C++标准的整数常量类型规则
核心规则:整数常量的默认类型
C/C++中,十进制整数常量的类型是能容纳它的最小类型,优先级顺序为:int → long int → long long int
也就是说:
- 如果常量值在
int范围内,默认是int类型 - 如果超过
int范围,就升级到long int(如果long能容纳);还不够就到long long
Case1 为什么输出不符合预期?
看这段关键代码:
lx1=2147483647 + 10 ;
2147483647刚好是int的最大值,10也是int类型,所以整个表达式是int类型的运算- 2147483647 + 10 会触发有符号整数溢出:这在C++标准中属于未定义行为,但x86平台通常按补码循环溢出,结果为
-2147483639(计算过程:2147483647+1=INT_MIN=-2147483648,再加9就是-2147483639) - 这个溢出后的int值被赋值给
long int类型的lx1,此时lx1的值是-2147483639 - 后续计算
lx1 - lx2:-2147483639 - 2100000000 = -4247483639,这个值远小于ix=500,所以进入else分支输出"ix is bigger",这就是不符合预期的根源
Case2 为什么正常?
再看这段关键代码:
lx1=2200000000 + 10 ;
2200000000已经超过了int的最大值2147483647,所以编译器自动把它识别为long int类型,10也会被隐式提升为long int- 整个运算在
long int范围内进行,2200000000+10=2200000010,无溢出 - 赋值给lx1后,
lx1-lx2=2200000010-2100000000=100000010,这个值远大于500,所以进入if分支输出"ix is not bigger",符合预期
解决方法
要避免Case1的问题,你可以用两种方式确保运算是在long int下进行:
- 给常量加后缀
L,显式声明为long int:
lx1=2147483647L + 10 ;
- 强制转换其中一个操作数为long int:
lx1=(long int)2147483647 + 10 ;
这样运算会在64位long int下执行,不会溢出,lx1的值会是2147483657,后续lx1-lx2=47483657,大于500,就能得到正确输出。
内容的提问来源于stack exchange,提问作者barfatchen
相关产品推荐
相关产品推荐

