c中long int的算术

arithmetic of long int in c

我在 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) , INT_MIN=(%d) \n",INT_MAX,INT_MIN);
int ix= 500  ;
long int lx1=0,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?!

引用了,还是想不通。

2147483647 + 10 的计算发生在 int 数据类型中,因为这两个值都适合 int。结果溢出,然后将结果扩展为long,但为时已晚。
在数字后缀 l 使其成为 long2147483647l + 10.

2200000000 对于 int 来说太大了,因此它是 long,所以添加按预期工作。

https://ideone.com/ClJI8F

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

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

因为两个操作数都是 ints 加法发生在 int.

因为 2200000000 不适合 32 位 int 它将是 longlong long 或 (unsigned int如果 C89).


当大小确实很重要时,始终为整数常量使用后缀:l 用于 long,u 用于无符号 -- 以及 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。