##C语言中的整型溢出
如果说我比别人看得更远些,那是因为我站在了巨人的肩上. ——牛顿
在C语言中,整型溢出分为有符号和无符号两种:
1. signed integer overflow : undefined behavior
2. unsigned integer overflow : safely wraps around (UINT_MAX + 1 yeild 0)
对于unsigned整型溢出,C的规范是有定义的——“溢出后的数会以2^(8*sizeof(type))作模运算”;对于signed整型的溢出,C的规范定义是“undefined behavior”。详细介绍请参考Basics of Integer Overflow和C语言的整型溢出问题。
##CPython如何判断整型溢出
当两个整型进行加、减、乘、除时都有可能产生溢出。下面以Cpython两个整数相加的实现为例说说Cpython如何判断整型溢出。
|
|
正如上篇博文讲的整型在内存中只是一串二进制数,看你怎样解释然后分为有符号数和无符号数,所以这里首先转换为无符号整型。如果条件判断语句((x\^a) >= 0 || (x\^b) >= 0)是false,就发生了溢出。这个if条件判断的是符号位。对于有符号整型,符号位为1表示负数,符号位为0表示正数。这个表达式>=0判断的就是符号位是否为0。
异或运算^中,两个bit相同为0,不同为1:
一个long能表达的数的范围是有限制的,两个long相加的情况不外乎下面6种:
可以看到,没有溢出的情况刚好x和a、b其中一个的符号位相同,而溢出的情况x跟a、b的符号位都不同。所以((x\^a) >= 0 || (x\^b) >= 0)就刚好能判断出来a+b有没有溢出。
这部分的内容是我在浏览cpython源码时遇到的疑问,google后发现大牛的讨论
cpython源码中关于整型溢出的注释: