2010-03-08 10 views
10

Czy istnieje ogólny sposób sprawdzania przepełnienia lub niedomiaru danego typu danych (uint32, int itp.)?Sprawdzanie niedopełnienia/przepełnienia w C++?

robię coś takiego:

uint32 a,b,c; 
... //initialize a,b,c 
if(b < c) { 
    a -= (c - b) 
} 

podczas drukowania po kilku iteracji, to wyświetla dużą liczbę takich jak: 4294963846.

+0

[Jak wykryć przepełnienie liczby całkowitej w C/C++?] (http://stackoverflow.com/q/199333/995714) –

Odpowiedz

9

Aby sprawdzić powyżej/dolnego w arytmetyce sprawdzić wynik w porównaniu do pierwotnych wartości.

uint32 a,b; 
//assign values 
uint32 result = a + b; 
if (result < a) { 
    //Overflow 
} 

dla konkretnego sprawdzenie byłoby:

if (a > (c-b)) { 
    //Underflow 
} 
+0

Dzięki. To na razie działa dobrze ... – Legend

+0

czy to w przypadku przepełnienia odpowiedź zawsze będzie podpisana (ujemna liczba całkowita)? – Faizan

+0

Przepełnienie liczb całkowitych bez znaku nigdy nie zostanie podpisane, a raczej będzie mniejszą liczbą całkowitą bez znaku niż jedna z pierwotnych wartości. –

4

Chyba gdybym chciał to zrobić chciałbym zrobić klasę, która symuluje typ danych, i zrobić to ręcznie (co byłoby powolne mogę sobie wyobrazić)

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; 

może być bardziej skomplikowane niż to, że będziesz musiał skończyć stosując określenie zamiast typedef ...

Zrobiłem podobną rzecz ze wskazówkami, aby sprawdzić, gdzie pamięć była zapisywana poza granicami. bardzo powolny, ale okazało się, że pamięć została uszkodzona

+0

Szukałem prostszego podejścia ... Ale w każdym razie, dzięki za to .. – Legend

+0

Istnieje wersja tego [nazywana SafeInt] (http: //safeint.codeplex .com /), o których dowiedziałem się dziś wieczorem. To chyba nie jest zły pomysł, aby używać czegoś takiego przez większość czasu, po prostu nie w kluczowym kodzie wydajności. – HostileFork

2

Cert ma dobre referencje zarówno dla signed integer overflow, który jest niezdefiniowanym zachowaniem i unsigned wrapping, który nie jest i obejmuje wszystkich operatorów.

Dokument przewiduje następujący kod sprawdzającego dla unsigned owijania w odejmowania za pomocą przesłanek jest następujący:

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; 
    } 
    /* ... */ 
} 

i post-warunków:

void func(unsigned int ui_a, unsigned int ui_b) { 
    unsigned int udiff = ui_a - ui_b; 
    if (udiff > ui_a) { 
    /* Handle error */ 
    } 
    /* ... */ 
} 

Jeśli jesteś gcc 5 można użyć __builtin_sub_overflow :

__builtin_sub_overflow(ui_a, ui_b, &udiff)