简体   繁体   中英

arithmetic of long int in c

I have the following source compiled in Linux 3.10.0-957.5.1.el7.x86_64,g++ version 4.8.5

Case1:

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");

compiled with warning :

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

and output :

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

and the following source 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");

compiled without warning and the output :

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

My question : Why Case1 output can be wrong ? lx1 and lx2 both long int, in this box it is size 8 bytes , how come 2200000000 is fine but 2147483647 is not for lx1 ?!

Comparing int with long and others is referd , still can not figure it out .

The calculation of 2147483647 + 10 happens with int datatypes, because both values fit into an int . The result overflows and then the result will be extended to a long , but that's too late.
Suffix the number with an l to make it a long : 2147483647l + 10 .

2200000000 is too big for an int , therefore it is a long , so the additon works as expected.

https://ideone.com/ClJI8F

The problem is that 2147483647 is of type int , not long. So the calculation 2147483647 + 10 overflows and behaviour is undefined . The usual arithmetic conversions convert each operand to

  • int
  • or if not representable in int to the type of the operand having greater rank, and signed is converted to unsigned if of equal rank!

Since both operands are int s the addition happens with int .

Since 2200000000 does not fit 32-bit int it will be long or long long or ( unsigned int if C89).


Always use a suffix for the integer constants when the size actually matter: l for longs, u for unsigned -- and ll for long long int; these can be coupled and are case sensitive so you can use LL for it to stand out from the others.

Finally, notice that long int need not be able to hold numbers greater than 2147483647 either, use long long int for that.


PS C89 did not have a long long int type at all, so in C89 vs C99+ the behaviour of the following would be different from each other if used as a constant expression on " long is 32-bit" machine!

-1 < 2147483647 + 10

It could result in 0 in C89 on 32-bit machine, and 1 in C99+ always.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM