计算机在进行运算时,可以表示的数据容量总是有限的,这也决定了一个具体的数据类型描述的数据量是非常有限的,这些数据在进行计算时很有可能超出该数据类型所能表示的范围发生溢出。一个健壮的程序必须正确处理好溢出,因为溢出发生时程序并没有发生崩溃的现象,只是计算结果和预期有很大差异,在复杂系统中存在致命的隐患。本文着重讨论如何正确预防及处理溢出问题。
在32位windows系统中,C语言定义的数据类型如下表:
数据类型 | 数据长度 |
char | 8bit ( -128 ~ 127 ) |
short | 16bit ( -32768 ~ 23767) |
int | 32bit (- 2147483648 ~ 2147483647) |
long | 32bit (- 2147483648 ~ 2147483647) |
long long | 64bit(-9223372036854775808 ~ 9223372036854775807) |
float | 32bit(-1.7*10^-308~1.7*10^308)有效数字7位 |
double | 64bit(-1.2*10^-4932~1.2*10^4932) 有效数字16位 |
对于整数的溢出判断,常见的办法是用一个更大容量的数来存储计算的结果,然后用这个大容量的数与计算因子数据类型的最大值作比较。例如,对于两个有符号型的整数a,b之和,判断是否发生溢出,需要将和与0x7FFFFFFF作比较,即
if(a + b > 0x7FFFFFFF )
{
溢出
}
但是这种做法是错误的,因为对于有符号的整数类型发生溢出时所有关于计算结果的假设均不可靠,需要将计算结果转为long类型或者转换成无符号类型才可靠,即:
if((unsigned int)a + (unsigned int)b > 0x7FFFFFFF)
{
// 溢出
}