。整型的加法
无符号和有符号加法有一样的规则:
假设x,y为w位整型数据。 x+y(如果其中一个操作数是无符号另一个有符号,有符号卡操作数会被强制转换为无符号)的结果等于位模式相加mod(2^w)。
。无符号加法溢出
w位的无符号数相加结果范围在0~2^(w+1)-2之内,可能需要w+1位表示,mod(2^w)相当于抛弃w位,如果没有发生加法溢出,w位为0,抛弃它对结果不产生影响,如果发生溢出,抛弃w位也就是把结果减去2^w。
例如2个4位的无符号数9+8,结果等于17,mod(2^w)之后等于17-16 == 1。而且,由于相加的两个操作数都不可能大于等于16(2^4),所以溢出后的结果不可能大于其中任何一个操作数。可以利用这个性质来检查结果是否溢出。
溢出的检查:如果没有发生溢出,x+y的值至少大于等于任何一个操作数。发生溢出,只要判断result(运算结果)是否小于其中任意一个操作数。
例:
return result < x;
。有符号加法溢出
两个w有符号整型数据相加的结果范围在-2^w~2^w - 2之内,可能需要w+1位来表示。溢出时,得到的结果同样相当于(x+y)mod(2^w)。
书中用了比较严谨的方法来说明有符号整型加法的溢出。但这里我用一个比较易于理解的图形来表述。
。负溢出
两个w位有符号整型数据相加如果发生负溢出,值在-2^w ~-2^(w - 1)-1范围之内,如图1。我们假设数据为w+1位,那么值在-2^w ~-2^(w - 1)-1范围之内就没有发生溢出,我们把这个范围映射到w+1位无符号表示,那么它对应图2中标出的部分2^w~3*2^(w-1)-1。明显它需要w+1位来表示,我们把值mod(2^w),也就是减去2^w,得到0~2^(w-1)-1范围内的值,这就是负数溢出得到的结果(图3)。可以根据两个负数(只有两个负数相加才有可能导致负溢出)相加的结果是否是正数来判断是否发生了负溢出。
(1)
(2)
(3)
。正溢出
如果发生正溢出,正数的值在2^(w-1)~2^w值域内,需要有符号的w+1位表示,图4。C中的整型(1) 中提到这个值域对应的是w位有符号正数所表示的负数部分,图5。可以根据检查两个有符号正数相加(只有两个正数相加才有可能导致正溢出)的结果是否是负数来判断是否发生了正溢出。
(4)
(5)