现在的位置: 首页 > 综合 > 正文

C陷阱与缺陷-整数的溢出

2017年12月15日 ⁄ 综合 ⁄ 共 659字 ⁄ 字号 评论关闭
文章目录

一 C语言整数运算

C语言中存在两类整数算数运算,有符号运算与无符号运算。

二 有符号整数运算中的溢出

在无符号算术运算中,没有所谓的”溢出“一说:所有的无符号运算都是以2的n次方为模,这里n是结果中的位数。

如果算术运算符的一个操作数是有符号整数,另一个是无符号整数,那么有符号整数会被被转换为无符号整数,”溢出“也不可能发生。

当两个操作数都是有符号整数时,”溢出“就有可能发生,而且”溢出“的结果是未定义的。当一个运算的结果发生”溢出“时,做出任何假设都是不安全的。

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

三 有符号整数溢出检测方案

1 方案一

将a和b都强制转换为无符号整数
if ((unsigned)a + (unsigned)b > INT_MAX)
    complain();
此处的INT_MAX是一个已定义的有符号整数常量,代表可能的最大整数值。INT_MAX绝对小于无符号的最大值,那么usigned(a)和unsigned(b)的和小于无符号的最大值,但可以判断它们的和是否大于有符号的INT_MAX。

2 方案二

不需要用到无符号算术运算
if (a > INT_MAX - b)
    complain();

抱歉!评论已关闭.