Проверка на подведем / переполнение в C ++?
-
25-09-2019 - |
Вопрос
Есть ли общий способ проверить на наличие переполнения или подведенного данного типа данных (UINT32, INT и т. Д.)?
Я делаю что-то вроде этого:
uint32 a,b,c;
... //initialize a,b,c
if(b < c) {
a -= (c - b)
}
Когда я печатаю после некоторых итераций, он отображает большое количество, такое как: 4294963846.
Решение
Чтобы проверить наверх / inlovflow в арифметике, проверьте результат по сравнению с исходными значениями.
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 )