C中long int的算术

问题描述

我在Linux 3.10.0-957.5.1.el7.x86_64,g ++版本4.8.5中编译了以下源代码

案例1:

printf("INT_MAX=(%d),INT_MIN=(%d) \n",INT_MAX,INT_MIN);
int ix= 500  ;
long int lx1=0,lx2=0;
lx1=2147483647 + 10 ;
lx2=2100000000 ;
if( ix < (lx1-lx2) )
    printf("ix is not bigger \n");
else
    printf("ix is bigger \n");

编译警告:

warning: integer overflow in expression [-Woverflow]
lx1=2147483647 + 10 ;

输出

INT_MAX=(2147483647),INT_MIN=(-2147483648) 
ix is bigger

和以下源Case2:

printf("INT_MAX=(%d),lx2=0;
lx1=2200000000 + 10 ;
lx2=2100000000 ;
if( ix < (lx1-lx2) )
    printf("ix is not bigger \n");
else
    printf("ix is bigger \n");

编译时没有警告,输出

INT_MAX=(2147483647),INT_MIN=(-2147483648) 
ix is not bigger 

我的问题:为什么Case1输出可能是错误的? lx1和lx2均为long int,在此框中为8字节大小,为什么2200000000可以,但是2147483647不适用于lx1吗?!

Comparing int with long and others 被引用,仍然无法弄清楚。

解决方法

2147483647 + 10的计算使用int数据类型进行,因为两个值都适合int。结果溢出,然后将结果扩展到long,但这为时已晚。
在数字后加上l,使其成为long2147483647l + 10

2200000000对于int而言太大,因此它是long,因此添加项可以按预期工作。

https://ideone.com/ClJI8F

,

问题是2147483647的类型为int,时间不长。因此,2147483647 + 10计算溢出,并且行为为未定义。通常的算术转换将每个操作数转换为

  • int
  • 或者如果不能在int中表示为具有更高等级的操作数的类型,并且如果等级相等,则将有符号转换为无符号!

由于两个操作数均为int,所以加法运算发生在int上。

由于2200000000不适合32位int,因此它将是longlong long或(如果是C89,则为 unsigned int )。


当大小实际上很重要时,始终对整数常量使用后缀:l代表long,u代表unsigned-和ll代表long long int;它们可以耦合并且区分大小写,因此您可以使用LL使其与众不同。

最后,请注意,long int也不必容纳大于2147483647的数字,为此请使用long long int


P.S。 C89根本没有long long int类型,因此在C89与C99 +中,如果在“ long是32位”机器上用作常量表达式,则以下行为会彼此不同!

-1 < 2147483647 + 10

在32位计算机上,C89中的结果可能为0,而在C99 +中则始终为1。