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
使其成为 long
:2147483647l + 10
.
2200000000
对于 int
来说太大了,因此它是 long
,所以添加按预期工作。
问题是 2147483647
是 int
类型,不长。因此计算 2147483647 + 10
溢出并且行为是 undefined。通常的算术转换将每个操作数转换为
int
- 或者如果在
int
中不可表示为具有更高秩的操作数的类型,并且如果具有相同的秩,则将有符号转换为无符号!
因为两个操作数都是 int
s 加法发生在 int
.
因为 2200000000
不适合 32 位 int
它将是 long
或 long 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。
我在 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
使其成为 long
:2147483647l + 10
.
2200000000
对于 int
来说太大了,因此它是 long
,所以添加按预期工作。
问题是 2147483647
是 int
类型,不长。因此计算 2147483647 + 10
溢出并且行为是 undefined。通常的算术转换将每个操作数转换为
int
- 或者如果在
int
中不可表示为具有更高秩的操作数的类型,并且如果具有相同的秩,则将有符号转换为无符号!
因为两个操作数都是 int
s 加法发生在 int
.
因为 2200000000
不适合 32 位 int
它将是 long
或 long 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。