整数溢出

本文探讨了C语言中整数算术运算的溢出问题,并提供了两种有效的方法来检测整数加法是否会发生溢出。通过示例代码展示了如何使用无符号整数转换或直接比较来避免潜在的溢出风险。

来自:C缺陷与陷阱3.9

c语言中存在两类整数算术运算,有符号运算与无符号运算。在无符号算术运算中,没有所谓的“溢出”一说:所有的无符号运算都是以2n次方为模,这里的n是结果中的位数。如果算术运算符的一个操作数为有符号整数,另一个为无符号整数,那么有符号整数会被转换成无符号整数,“溢出”也不可能发生。但是,当两个操作数都是有符号数时,溢出就有可能发生,而且溢出的结果是未定义的。当一个运算的结果发生溢出时,做出任何假设都是不安全的。

 

假如ab是两个非负整型变量,我们需要检查a+b是否会溢出,一种想当然的办法是这样:

if( a + b < 0 )

{

    complain();

}

这并不能正常运行。当a+b确实发生溢出时,所有关于结果如何的假设都不再可靠。例如,在某些机器上,加法运算将设置一个内部寄存器为四种状态之一:正、负、零、溢出。在这种机器上,c编译器完全有理由这样来实现上面的例子,即ab相加,然后检查内部寄存器的标志是否为“负”。当加法操作发生溢出时,这个内部寄存器的状态是溢出而不是负,那么if的语句的检查就会失败。

 

一种正确的方式是将ab都强制转换为无符号整数:

if( ( unsigned )a + ( unsigned )b > INT_MAX )

{

    complain();

}

此处的INT_MAX是一个已定义的常量,代表可能的最大整数值。ANSI C标准在<limits.h>中定义了INT_MAX。不需要用到无符号算术运算的另外一种可行办法是:

if( a > INT_MAX - b )

{

    complain();

}

#include <limits.h>

#include <stdio.h>

 

int main()

{

    int a = 2147483640, b = 2147483640, c = 0, d = 0;

   

    if( ( unsigned )a + ( unsigned )b > INT_MAX )

    {

        printf( " 最大的整数是:%d, 最小的整数是:%d /n",INT_MAX,INT_MIN );

        printf( " INT_MAX的值为2147483647INT_MIN的值为-2147483648  /n" );

    }

   

    c = a + b;   

    d = -a + -b;

    printf( "***%d***%d***/n", c, d );

    getchar();

    return 0;

}

 

整数溢出通常发生在对整数进行赋值或算术运算时,因操作结果超出了该整数类型所能表示的范围。下面从不同编程语言的角度介绍整数溢出的实现方法。 ### C语言实现整数溢出 在C语言中,整数溢出分为无符号整型溢出和有符号整型溢出。 #### 无符号整型溢出 无符号整型溢出时,结果会对该类型能表示的最大值加1取模。 ```c #include <stdio.h> int main() { unsigned int max = 0xFFFFFFFF; // 无符号整型的最大值 unsigned int result = max + 1; printf("max + 1 = %u\n", result); // 输出结果为0 return 0; } ``` #### 有符号整型溢出 有符号整型溢出的行为是未定义的,但在大多数编译器中,会发生回绕现象。 ```c #include <stdio.h> int main() { int max = 0x7FFFFFFF; // 有符号整型的最大值 int result = max + 1; printf("max + 1 = %d\n", result); // 输出结果为-2147483648 return 0; } ``` ### Java实现整数溢出 在Java中,一个`int`型变量占32位,能表示的数据范围为 -2³¹~2³¹ - 1之间的整数。当发生溢出时,编译器通常不会报错。 ```java public class IntegerOverflow { public static void main(String[] args) { int max = Integer.MAX_VALUE; // 整型的最大值 int result = max + 1; System.out.println("max + 1 = " + result); // 输出结果为-2147483648 } } ``` ### Python实现整数溢出 在Python 2时代,整型有`int`类型和`long`长整型,长整型不存在溢出问题。在Python 3后,统一使用了长整型,不会发生溢出。不过可以模拟溢出的效果。 ```python import ctypes # 模拟有符号32位整数溢出 max_int = 2**31 - 1 result = ctypes.c_int32(max_int + 1).value print(f"max + 1 = {result}") # 输出结果为-2147483648 ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值