方法一:
境遇:假设要判断两个整数的加法运算是否溢出。
C#中的checked/unchecked关键字能和方便的检查运算是否溢出,但是我们在C++中怎么做呢?溢出也不像C#会抛出异常,别忘了C/C++的特点:我们可以直接操纵底层硬件!把寄存器溢出标志位取出来就可以了。虽然只对加法做了溢出判断,但有了下面这段示例也能判断其它运算的溢出了。
//Copyright By Renjiachao //By Renjiachao 2010-10-13 #include<iostream> #include<string> using namespace std; class SafeInt //signed int { friend const SafeInt operator+(const SafeInt& lhs, const SafeInt& rhs); friend ostream& operator<<(ostream& out, const SafeInt& si) { out<<si.val; return out; } public: SafeInt(int v=0):val(v) {} operator int() {return val;} SafeInt& operator+=(const SafeInt& rhs) { val += rhs.val; unsigned long dwEAX = 0; __asm //汇编代码鸣谢:贾宁宇 { PUSH EAX //压入EAX寄存器的值作为保护 PUSHFD //将EFLAGS寄存器的全部内容压入堆栈 POP EAX //把刚刚入栈的EFLAGS寄存器的值取出放入EAX MOV dwEAX,EAX //把EAX中的值放入dwEAX变量中 POP EAX //恢复EAX寄存器的值 } if (dwEAX & 0x00000800) //取出第11(基于0)位的值 throw overflow_error("溢出"); return *this; } private: int val; }; const SafeInt operator+(const SafeInt& lhs, const SafeInt& rhs) { SafeInt temp(lhs); temp+=rhs; return temp; } int main() { SafeInt i1 = 10; SafeInt i2 = INT_MAX - 11; SafeInt iSum = 0; try { iSum = i1 + i2; //不溢出 cout<<i1<<" + "<<i2<<" = "<<iSum<<endl; iSum = iSum + i1; //溢出 cout<<i1<<" + "<<i2<<" = "<<iSum<<endl; } catch(overflow_error & e) { cout<<e.what()<<endl; } return 0; }
代码中的说明:
OF--溢出标志
EFLAGS 寄存器
的标志位大致如下表所示:
方法二:
if ((unsigned)a+(unsigned)b > INT_MAX) complain();
此处的INT_MAXSHI是一个已定义的常量,代表可能的最大整数值。ANSI C标准在<limits.h>中定义了INT_MAX;如果是在其他C语言实现上,你也需要自己重新定义。
if (a > INT_MAX -B) complain();
方法三:
static PyObject * int_add(PyIntObject *v, PyIntObject *w) { register long a, b, x; CONVERT_TO_LONG(v, a); CONVERT_TO_LONG(w, b); /* casts in the line below avoid undefined behaviour on overflow */ x = (long)((unsigned long)a + b); if ((x^a) >= 0 || (x^b) >= 0) return PyInt_FromLong(x); return PyLong_Type.tp_as_number->nb_add((PyObject *)v, (PyObject *)w); }