有没有一种通用的方法来检查给定数据类型(uint32、int等)是否溢出或下溢?
我正在做这样的事情:
uint32 a,b,c;
... //initialize a,b,c
if(b < c) {
a -= (c - b)
}
在我迭代若干次后输出 a 时,它显示一个很大的数值,例如:4294963846。
有没有一种通用的方法来检查给定数据类型(uint32、int等)是否溢出或下溢?
我正在做这样的事情:
uint32 a,b,c;
... //initialize a,b,c
if(b < c) {
a -= (c - b)
}
在我迭代若干次后输出 a 时,它显示一个很大的数值,例如:4294963846。
要检查算术运算的溢出/下溢,请将结果与原始值进行比较。
uint32 a,b;
//assign values
uint32 result = a + b;
if (result < a) {
//Overflow
}
针对你的情况,检查的方法如下:
if (a > (c-b)) {
//Underflow
}
我想,如果我想要做到这一点,我会创建一个模拟数据类型的类,并手动完成它(这可能会很慢)。
class MyInt
{
int val;
MyInt(const int&nval){ val = nval;} // cast from int
operator int(){return val;} // cast to int
// then just overload ALL the operators... putting your check in
};
//typedef int sint32;
typedef MyInt sint32;
这可能比那更棘手,你可能需要使用定义而不是typedef...
我用指针做了类似的事情,检查内存是否被写在边界之外。虽然很慢,但确实找到了内存损坏的位置。
void func(unsigned int ui_a, unsigned int ui_b) {
unsigned int udiff;
if (ui_a < ui_b){
/* Handle error */
} else {
udiff = ui_a - ui_b;
}
/* ... */
}
并且带有后置条件:
void func(unsigned int ui_a, unsigned int ui_b) {
unsigned int udiff = ui_a - ui_b;
if (udiff > ui_a) {
/* Handle error */
}
/* ... */
}
如果您使用的是gcc 5,您可以使用__builtin_sub_overflow
:
__builtin_sub_overflow( ui_a, ui_b, &udiff )
如果有一个更大的(x2大小)整数类型可用,我将在此处提供另一种可能的方法。在这种情况下,可以通过稍微增加计算量来防止溢出发生。
// https://gcc.godbolt.org/z/fh9G6Eeah
#include <exception>
#include <limits>
#include <iostream>
using integer_t = uint32_t; // The desired type
using bigger_t = uint64_t; // Bigger type
constexpr integer_t add(const integer_t a, const integer_t b)
{
static_assert(sizeof(bigger_t)>=2*sizeof(integer_t));
constexpr bigger_t SUP = std::numeric_limits<integer_t>::max();
constexpr bigger_t INF = std::numeric_limits<integer_t>::min();
// Using larger type for operation
bigger_t res = static_cast<bigger_t>(a) + static_cast<bigger_t>(b);
// Check overflows
if(res>SUP) throw std::overflow_error("res too big");
else if(res<INF) throw std::overflow_error("res too small");
// Back to the original type
return static_cast<integer_t>(res); // No danger of narrowing here
}
//---------------------------------------------------------------------------
int main()
{
std::cout << add(100,1) << '\n';
std::cout << add(std::numeric_limits<integer_t>::max(),1) << '\n';
}