Sdílet prostřednictvím


SafeInt – třída

Rozšiřuje celá čísla, aby se zabránilo přetečení celého čísla a umožňuje porovnat různé typy celých čísel.

Poznámka:

Nejnovější verze knihovny SafeInt se nachází na adrese https://github.com/dcleblanc/SafeInt. Pokud chcete použít knihovnu SafeInt, naklonujte úložiště a #include "SafeInt.hpp"

Syntaxe

template<typename T, typename E = _SAFEINT_DEFAULT_ERROR_POLICY>
class SafeInt;

Parametry

T
Typ celočíselného nebo logického parametru, který SafeInt nahrazuje.

E
Výčtový datový typ, který definuje zásady zpracování chyb.

U
Typ celočíselného nebo logického parametru pro sekundární operand.

rhs
[v] Vstupní parametr, který představuje hodnotu na pravé straně operátoru v několika samostatných funkcích.


[v] Vstupní parametr, který představuje hodnotu na pravé straně operátoru v několika samostatných funkcích.

bity
[v] Vstupní parametr, který představuje hodnotu na pravé straně operátoru v několika samostatných funkcích.

Členové

Veřejné konstruktory

Název Popis
SafeInt::SafeInt Výchozí konstruktor.

Operátory přiřazení

Název Syntaxe
= template<typename U>
SafeInt<T,E>& operator= (const U& rhs)
= SafeInt<T,E>& operator= (const T& rhs) throw()
= template<typename U>
SafeInt<T,E>& operator= (const SafeInt<U, E>& rhs)
= SafeInt<T,E>& operator= (const SafeInt<T,E>& rhs) throw()

Operátory přetypování

Název Syntaxe
bool operator bool() throw()
char operator char() const
podepsaný znak operator signed char() const
unsigned char operator unsigned char() const
__int16 operator __int16() const
__int16 bez znaménka operator unsigned __int16() const
__int32 operator __int32() const
nepodepsaný __int32 operator unsigned __int32() const
long operator long() const
unsigned long operator unsigned long() const
__int64 operator __int64() const
nepodepsaný __int64 operator unsigned __int64() const
wchar_t operator wchar_t() const

Operátory porovnání

Název Syntaxe
< template<typename U>

bool operator< (U rhs) const throw()
< bool operator< (SafeInt<T,E> rhs) const throw()
>= template<typename U>

bool operator>= (U rhs) const throw()
>= Bool operator>= (SafeInt<T,E> rhs) const throw()
> template<typename U>

bool operator> (U rhs) const throw()
> Bool operator> (SafeInt<T,E> rhs) const throw()
<= template<typename U>

bool operator<= (U rhs) const throw()
<= bool operator<= (SafeInt<T,E> rhs) const throw()
== template<typename U>

bool operator== (U rhs) const throw()
== bool operator== (bool rhs) const throw()
== bool operator== (SafeInt<T,E> rhs) const throw()
!= template<typename U>

bool operator!= (U rhs) const throw()
!= bool operator!= (bool b) const throw()
!= bool operator!= (SafeInt<T,E> rhs) const throw()

Aritmetické operátory

Název Syntaxe
+ const SafeInt<T,E>& operator+ () const throw()
- SafeInt<T,E> operator- () const
++ SafeInt<T,E>& operator++ ()
-- SafeInt<T,E>& operator-- ()
% template<typename U>

SafeInt<T,E> operator% (U rhs) const
% SafeInt<T,E> operator% (SafeInt<T,E> rhs) const
%= template<typename U>

SafeInt<T,E>& operator%= (U rhs)
%= template<typename U>

SafeInt<T,E>& operator%= (SafeInt<U, E> rhs)
* template<typename U>

SafeInt<T,E> operator* (U rhs) const
* SafeInt<T,E> operator* (SafeInt<T,E> rhs) const
*= SafeInt<T,E>& operator*= (SafeInt<T,E> rhs)
*= template<typename U>

SafeInt<T,E>& operator*= (U rhs)
*= template<typename U>

SafeInt<T,E>& operator*= (SafeInt<U, E> rhs)
/ template<typename U>

SafeInt<T,E> operator/ (U rhs) const
/ SafeInt<T,E> operator/ (SafeInt<T,E> rhs ) const
/= SafeInt<T,E>& operator/= (SafeInt<T,E> i)
/= template<typename U>

SafeInt<T,E>& operator/= (U i)
/= template<typename U>

SafeInt<T,E>& operator/= (SafeInt<U, E> i)
+ SafeInt<T,E> operator+ (SafeInt<T,E> rhs) const
+ template<typename U>

SafeInt<T,E> operator+ (U rhs) const
+= SafeInt<T,E>& operator+= (SafeInt<T,E> rhs)
+= template<typename U>

SafeInt<T,E>& operator+= (U rhs)
+= template<typename U>

SafeInt<T,E>& operator+= (SafeInt<U, E> rhs)
- template<typename U>

SafeInt<T,E> operator- (U rhs) const
- SafeInt<T,E> operator- (SafeInt<T,E> rhs) const
-= SafeInt<T,E>& operator-= (SafeInt<T,E> rhs)
-= template<typename U>

SafeInt<T,E>& operator-= (U rhs)
-= template<typename U>

SafeInt<T,E>& operator-= (SafeInt<U, E> rhs)

Logické operátory

Název Syntaxe
! bool operator !() const throw()
~ SafeInt<T,E> operator~ () const throw()
<< template<typename U>

SafeInt<T,E> operator<< (U bits) const throw()
<< template<typename U>

SafeInt<T,E> operator<< (SafeInt<U, E> bits) const throw()
<<= template<typename U>

SafeInt<T,E>& operator<<= (U bits) throw()
<<= template<typename U>

SafeInt<T,E>& operator<<= (SafeInt<U, E> bits) throw()
>> template<typename U>

SafeInt<T,E> operator>> (U bits) const throw()
>> template<typename U>

SafeInt<T,E> operator>> (SafeInt<U, E> bits) const throw()
>>= template<typename U>

SafeInt<T,E>& operator>>= (U bits) throw()
>>= template<typename U>

SafeInt<T,E>& operator>>= (SafeInt<U, E> bits) throw()
& SafeInt<T,E> operator& (SafeInt<T,E> rhs) const throw()
& template<typename U>

SafeInt<T,E> operator& (U rhs) const throw()
&= SafeInt<T,E>& operator&= (SafeInt<T,E> rhs) throw()
&= template<typename U>

SafeInt<T,E>& operator&= (U rhs) throw()
&= template<typename U>

SafeInt<T,E>& operator&= (SafeInt<U, E> rhs) throw()
^ SafeInt<T,E> operator^ (SafeInt<T,E> rhs) const throw()
^ template<typename U>

SafeInt<T,E> operator^ (U rhs) const throw()
^= SafeInt<T,E>& operator^= (SafeInt<T,E> rhs) throw()
^= template<typename U>

SafeInt<T,E>& operator^= (U rhs) throw()
^= template<typename U>

SafeInt<T,E>& operator^= (SafeInt<U, E> rhs) throw()
| SafeInt<T,E> operator| (SafeInt<T,E> rhs) const throw()
| template<typename U>

SafeInt<T,E> operator| (U rhs) const throw()
|= SafeInt<T,E>& operator|= (SafeInt<T,E> rhs) throw()
|= template<typename U>

SafeInt<T,E>& operator|= (U rhs) throw()
|= template<typename U>

SafeInt<T,E>& operator|= (SafeInt<U, E> rhs) throw()

Poznámky

Třída SafeInt chrání před přetečením celého čísla v matematických operacích. Zvažte například přidání dvou 8bitových celých čísel: jedno má hodnotu 200 a druhá má hodnotu 100. Správná matematická operace by byla 200 + 100 = 300. Kvůli 8bitovému celočíselnému limitu se však horní bit ztratí a kompilátor vrátí jako výsledek hodnotu 44 (300 –28). Jakákoli operace, která závisí na této matematické rovnici, vygeneruje neočekávané chování.

Třída SafeInt zkontroluje, zda dojde k aritmetickému přetečení nebo zda se kód pokusí dělit nulou. V obou případech třída volá obslužnou rutinu chyby, která upozorní program na potenciální problém.

Tato třída také umožňuje porovnat dva různé typy celých čísel, pokud jsou SafeInt objekty. Při porovnávání je obvykle nutné čísla nejprve převést na stejný typ. Přetypování jednoho čísla na jiný typ často vyžaduje kontroly, aby se zajistilo, že nedojde ke ztrátě dat.

Tabulka Operators v tomto tématu uvádí matematické a porovnávací operátory podporované SafeInt třídou. Většina matematických operátorů vrací SafeInt objekt typu T.

Operace porovnání mezi celočíselným typem SafeInt lze provádět v obou směrech. Například obě SafeInt<int>(x) < y a y> SafeInt<int>(x) jsou platné a vrátí stejný výsledek.

Mnoho binárních operátorů nepodporuje použití dvou různých SafeInt typů. Jedním z příkladů je & operátor. SafeInt<T, E> & int se podporuje, ale SafeInt<T, E> & SafeInt<U, E> není. V druhém příkladu kompilátor neví, jaký typ parametru se má vrátit. Jedním z řešení tohoto problému je přetypování druhého parametru zpět na základní typ. Pomocí stejných parametrů to lze provést pomocí SafeInt<T, E> & (U)SafeInt<U, E>.

Poznámka:

Pro všechny bitové operace by měly mít dva různé parametry stejnou velikost. Pokud se velikosti liší, kompilátor vyvolá výjimku ASSERT . Výsledky této operace nelze zaručit, že budou přesné. Pokud chcete tento problém vyřešit, přetypujte menší parametr, dokud nebude stejný jako větší parametr.

U operátorů směny vyvolá posun více bitů, než existuje pro typ šablony, vyvolá výjimku ASSERT. To nebude mít žádný vliv v režimu vydání. Pro operátory směn je možné kombinovat dva typy parametrů SafeInt, protože návratový typ je stejný jako původní typ. Číslo na pravé straně operátoru označuje pouze počet bitů, které se mají posunout.

Při logickém porovnání s objektem SafeInt je porovnání přísně aritmetické. Představte si například tyto výrazy:

  • SafeInt<uint>((uint)~0) > -1

  • ((uint)~0) > -1

První příkaz se přeloží na true, ale druhý příkaz se přeloží na false. Bitové negace 0 je 0xFFFFFFFF. Ve druhém příkazu výchozí relační operátor porovnává 0xFFFFFFFF s 0xFFFFFFFF a považuje je za stejné. Relační operátor třídy SafeInt zjistí, že druhý parametr je záporný, zatímco první parametr je nepodepsaný. I když je bitová reprezentace identická, SafeInt logický operátor si uvědomuje, že celé číslo bez znaménka je větší než -1.

Při použití SafeInt třídy spolu s ternárním operátorem ?: buďte opatrní. Podívejte se na následující řádek kódu.

Int x = flag ? SafeInt<unsigned int>(y) : -1;

Kompilátor ho převede na toto:

Int x = flag ? SafeInt<unsigned int>(y) : SafeInt<unsigned int>(-1);

Pokud flag je false, kompilátor vyvolá výjimku místo přiřazení hodnoty -1 k x. Abyste se tomuto chování vyhnuli, je správný kód, který se má použít, následující řádek.

Int x = flag ? (int) SafeInt<unsigned int>(y) : -1;

T a U může být přiřazen logický typ, typ znaku nebo celočíselné typy. Celočíselné typy mohou být podepsány nebo bez znaménka a libovolnou velikost od 8 bitů do 64 bitů.

Poznámka:

SafeInt I když třída přijímá jakýkoli druh celého čísla, provádí efektivněji s nepodepsanými typy.

E je mechanismus zpracování chyb, který SafeInt se používá. V knihovně SafeInt jsou k dispozici dva mechanismy zpracování chyb. Výchozí zásada je SafeIntErrorPolicy_SafeIntException, která vyvolá výjimku Třídy SafeIntException , když dojde k chybě. Další zásada je SafeIntErrorPolicy_InvalidParameter, která program zastaví, pokud dojde k chybě.

Existují dvě možnosti přizpůsobení zásad chyb. První možností je nastavit parametr E při vytváření .SafeInt Tuto možnost použijte, pokud chcete změnit zásady zpracování chyb pouze pro jednu SafeInt. Druhou možností je definovat _SAFEINT_DEFAULT_ERROR_POLICY jako přizpůsobenou třídu zpracování chyb před zahrnutím SafeInt knihovny. Tuto možnost použijte, pokud chcete změnit výchozí zásady zpracování chyb pro všechny instance SafeInt třídy v kódu.

Poznámka:

Přizpůsobená třída, která zpracovává chyby z knihovny SafeInt, by neměla vrátit ovládací prvek do kódu, který volal obslužnou rutinu chyby. Po zavolání obslužné rutiny chyby nemůže být výsledek SafeInt operace důvěryhodný.

Hierarchie dědičnosti

SafeInt

Požadavky

Hlavička: SafeInt.hpp

Poznámka:

Nejnovější verze této knihovny se nachází na adrese https://github.com/dcleblanc/SafeInt. Naklonujte knihovnu a zahrňte SafeInt.hpp pro použití knihovny SafeInt. Upřednostňujte toto úložiště GitHubu před <safeint.h>. Jedná se o moderní verzi safeint.h>, která obsahuje malý počet oprav chyb, používá moderní funkce jazyka C++, což vede k efektivnějšímu <kódu a je přenositelný na libovolnou platformu pomocí kompilátorů gcc, clang nebo Intel.

Příklad

#include "SafeInt.hpp" // set path to your clone of the SafeInt GitHub repo (https://github.com/dcleblanc/SafeInt)

int main()
{
    int divisor = 3;
    int dividend = 6;
    int result;

    bool success = SafeDivide(dividend, divisor, result); // result = 2
    success = SafeDivide(dividend, 0, result); // expect fail. result isn't modified.
}

Obor názvů: žádný

SafeInt::SafeInt

SafeInt Vytvoří objekt.

SafeInt() throw

SafeInt (const T& i) throw ()

SafeInt (bool b) throw ()

template <typename U>
SafeInt (const SafeInt <U, E>& u)

I template <typename U>
SafeInt (const U& i)

Parametry

i
[v] Hodnota nového SafeInt objektu. To musí být parametr typu T nebo U v závislosti na konstruktoru.

b
[v] Logická hodnota nového SafeInt objektu.

u
[v] A SafeInt typu U. Nový SafeInt objekt bude mít stejnou hodnotu jako u, ale bude mít typ T.

U Typ dat uložených v souboru SafeInt. Může to být logický typ, znak nebo celé číslo. Pokud se jedná o celočíselné číslo, může být podepsáno nebo bez znaménka a může být mezi 8 a 64 bity.

Poznámky

Vstupním parametrem konstruktoru, i nebo u musí být logický typ, znak nebo celé číslo. Pokud se jedná o jiný typ parametru, SafeInt třída volá static_assert označují neplatný vstupní parametr.

Konstruktory, které používají typ U šablony, automaticky převedou vstupní parametr na typ určený T. Třída SafeInt převede data bez ztráty dat. Hlásí obslužnou rutinu E chyby, pokud nemůže převést data na typ T bez ztráty dat.

Pokud vytvoříte SafeInt z logického parametru, musíte hodnotu inicializovat okamžitě. Nelze vytvořit SafeInt pomocí kódu SafeInt<bool> sb;. Tím se vygeneruje chyba kompilace.