1.当数据超出了类型的最值或者有符号数被解析成无符号数时,可能会发生溢出。整型溢出的形式有:(1)存储溢出(2)运算溢出(3)符号导致的溢出
对于存储溢出,假如
int m=0x1000;
char n=m;
printf(“%d\n”,n)
结果会输出0,因为m占据4个字节的存储空间,而n占有一个,m赋值给n时,仅仅把最低字节给了n。
对于运算溢出,假如
unsigned char a=255;
unsigned char b=a+1;
printf(“%d\n”,b)
无符号字符型的数据最大为255,如果a+1,则会溢出,程序输出0.
对于符号导致的溢出,写程序:
int a[5]={1,2,3,4,5};
# define NUM sizeof(a)/sizeof(a[0])
int main()
{
int d=-1;
if(d<NUM)
printf("d is less than NUM");
else
printf("d is not less than NUM");
return 0;
}
程序的输出结果是 d is not less than NUM,因为在NUM是无符号整型的数据,d在与其比较时d被提升为无符号整型,变成了一个很大的整数。
整型溢出可能导致死循环,内存分配错误等,如
int *a=(int *)malloc(N*sizeof(int)),如果N是个很大的数,N*sizeof(int)会导致溢出,最终a指向的内存块远小于程序员要求的大小,这会引发错误甚至系统攻击。
防止整型溢出,在编码时尽量不使用无符号整型,使用有符号整型类型的变量,不用担心负数被编译器解释成很大的整数,会让程序更加安全。
2.判断整型溢出
对于无符号数的加法,判断整型溢出,可以这样:
void fun(unsigned int a,unsigned int b)
{
if(a>UINT_MAX-b) //UINT_MAX为无符号整型的最大值,在VC编译器中为0xffffffff
{
printf("overflow\n");
return ;
}
else
printf("%d\n",a+b);
}
对于无符号的乘法,可以这样判断溢出:
void fun(unsigned int a,unsigned int b)
{
if(a>UINT_MAX/b)
{
printf("overflow\n");
return ;
}
else
{
printf("%d\n",a*b);
}
}
对于有符号数的加法运算,判断溢出的方法与无符号数类似,但要考虑符号问题:
void fun(int a,int b)
{
if(a>0&&b>0&&a>INT_MAX-b) //INT_MAX为有符号整型的最大值,VC编译器中为2147483647
{
printf("overflow\n");
return ;
}
if(a<0&&b<0&&a<INT_MIN-b) //INT_MAX为无符号整型的最小值,VC编译器中为-2147483648
{
printf("overflow\n");
return ;
}
else
printf("%d\n",a+b);
}