Bagikan melalui


Kelas SafeInt

Memperluas primitif bilangan bulat untuk membantu mencegah luapan bilangan bulat dan memungkinkan Anda membandingkan berbagai jenis bilangan bulat.

Catatan

Versi terbaru pustaka SafeInt terletak di https://github.com/dcleblanc/SafeInt. Untuk menggunakan pustaka SafeInt, klon repositori dan #include "SafeInt.hpp"

Sintaks

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

Parameter

T
Jenis parameter bilangan bulat atau Boolean yang SafeInt menggantikan.

E
Jenis data enumerasi yang menentukan kebijakan penanganan kesalahan.

U
Jenis parameter bilangan bulat atau Boolean untuk operand sekunder.

rhs
[di] Parameter input yang mewakili nilai di sisi kanan operator dalam beberapa fungsi yang berdiri sendiri.

i
[di] Parameter input yang mewakili nilai di sisi kanan operator dalam beberapa fungsi yang berdiri sendiri.

Bit
[di] Parameter input yang mewakili nilai di sisi kanan operator dalam beberapa fungsi yang berdiri sendiri.

Anggota

Konstruktor Publik

Nama Deskripsi
SafeInt::SafeInt Konstruktor default.

Operator Penugasan

Nama Sintaks
= 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()

Operator Casting

Nama Sintaks
bool operator bool() throw()
char operator char() const
karakter yang ditandatangani operator signed char() const
char yang tidak bertanda operator unsigned char() const
__int16 operator __int16() const
__int16 yang tidak ditandatangani operator unsigned __int16() const
__int32 operator __int32() const
__int32 yang tidak ditandatangani operator unsigned __int32() const
long operator long() const
panjang tidak ditandatangani operator unsigned long() const
__int64 operator __int64() const
__int64 tidak bertanda operator unsigned __int64() const
wchar_t operator wchar_t() const

Operator perbandingan

Nama Sintaks
< 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()

Operasi Aritmatika

Nama Sintaks
+ 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)

Operator Logis

Nama Sintaks
! 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()

Keterangan

Kelas SafeInt melindungi dari luapan bilangan bulat dalam operasi matematika. Misalnya, pertimbangkan untuk menambahkan dua bilangan bulat 8-bit: satu memiliki nilai 200 dan yang kedua memiliki nilai 100. Operasi matematika yang benar adalah 200 + 100 = 300. Namun, karena batas bilangan bulat 8-bit, bit atas akan hilang dan pengkompilasi akan mengembalikan 44 (300 - 28) sebagai hasilnya. Setiap operasi yang bergantung pada persamaan matematika ini akan menghasilkan perilaku tak terduga.

Kelas SafeInt memeriksa apakah luapan aritmatika terjadi atau apakah kode mencoba membagi dengan nol. Dalam kedua kasus, kelas memanggil penangan kesalahan untuk memperingatkan program potensi masalah.

Kelas ini juga memungkinkan Anda membandingkan dua jenis bilangan bulat yang berbeda selama mereka adalah SafeInt objek. Biasanya, ketika Anda melakukan perbandingan, Anda harus terlebih dahulu mengonversi angka menjadi jenis yang sama. Mentransmisikan satu angka ke jenis lain sering kali memerlukan pemeriksaan untuk memastikan bahwa tidak ada kehilangan data.

Tabel Operator dalam topik ini mencantumkan operator matematika dan perbandingan yang didukung oleh SafeInt kelas . Sebagian besar operator matematika mengembalikan SafeInt objek jenis T.

Operasi perbandingan antara jenis integral SafeInt dan dapat dilakukan di kedua arah. Misalnya, dan SafeInt<int>(x) < y y> SafeInt<int>(x) valid dan akan mengembalikan hasil yang sama.

Banyak operator biner tidak mendukung penggunaan dua jenis yang berbeda SafeInt . Salah satu contohnya adalah & operator. SafeInt<T, E> & int didukung, tetapi SafeInt<T, E> & SafeInt<U, E> tidak. Dalam contoh terakhir, pengkompilasi tidak tahu jenis parameter apa yang akan dikembalikan. Salah satu solusi untuk masalah ini adalah melemparkan parameter kedua kembali ke jenis dasar. Dengan menggunakan parameter yang sama, ini dapat dilakukan dengan SafeInt<T, E> & (U)SafeInt<U, E>.

Catatan

Untuk operasi bitwise apa pun, dua parameter yang berbeda harus berukuran sama. Jika ukurannya berbeda, pengkompilasi akan memberikan pengecualian ASSERT . Hasil operasi ini tidak dapat dijamin akurat. Untuk mengatasi masalah ini, transmisikan parameter yang lebih kecil hingga ukurannya sama dengan parameter yang lebih besar.

Untuk operator shift, menggeser lebih banyak bit daripada yang ada untuk jenis templat akan memberikan pengecualian ASSERT. Ini tidak akan berpengaruh dalam mode rilis. Mencampur dua jenis parameter SafeInt dimungkinkan untuk operator shift karena jenis pengembaliannya sama dengan jenis aslinya. Angka di sisi kanan operator hanya menunjukkan jumlah bit yang akan digeser.

Ketika Anda melakukan perbandingan logis dengan objek SafeInt, perbandingannya sangat aritmatika. Misalnya, pertimbangkan ekspresi ini:

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

  • ((uint)~0) > -1

Pernyataan pertama diselesaikan ke true, tetapi pernyataan kedua diselesaikan ke false. Negasi bitwise 0 0xFFFFFFFF. Dalam pernyataan kedua, operator perbandingan default membandingkan 0xFFFFFFFF dengan 0xFFFFFFFF dan menganggapnya sama. Operator perbandingan SafeInt untuk kelas menyadari bahwa parameter kedua negatif sedangkan parameter pertama tidak ditandatangani. Oleh karena itu, meskipun representasi bit identik, SafeInt operator logis menyadari bahwa bilangan bulat yang tidak ditandatangani lebih besar dari -1.

Berhati-hatilah saat Anda menggunakan SafeInt kelas bersama dengan ?: operator terner. Pertimbangkan baris kode berikut.

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

Pengkompilasi mengonversinya ke ini:

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

Jika flag adalah false, pengkompilasi melempar pengecualian alih-alih menetapkan nilai -1 ke x. Oleh karena itu, untuk menghindari perilaku ini, kode yang benar untuk digunakan adalah baris berikut.

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

T dan U dapat diberi jenis Boolean, jenis karakter, atau jenis bilangan bulat. Jenis bilangan bulat dapat ditandatangani atau tidak ditandatangani dan ukuran apa pun dari 8 bit hingga 64 bit.

Catatan

SafeInt Meskipun kelas menerima semua jenis bilangan bulat, kelas ini berkinerja lebih efisien dengan jenis yang tidak ditandatangani.

E adalah mekanisme penanganan kesalahan yang SafeInt menggunakan. Dua mekanisme penanganan kesalahan disediakan dengan pustaka SafeInt. Kebijakan default adalah SafeIntErrorPolicy_SafeIntException, yang melempar pengecualian Kelas SafeIntException saat kesalahan terjadi. Kebijakan lainnya adalah SafeIntErrorPolicy_InvalidParameter, yang menghentikan program jika terjadi kesalahan.

Ada dua opsi untuk menyesuaikan kebijakan kesalahan. Opsi pertama adalah mengatur parameter E saat Anda membuat SafeInt. Gunakan opsi ini saat Anda ingin mengubah kebijakan penanganan kesalahan hanya untuk satu SafeInt. Opsi lainnya adalah menentukan _SAFEINT_DEFAULT_ERROR_POLICY menjadi kelas penanganan kesalahan yang disesuaikan sebelum Anda menyertakan SafeInt pustaka. Gunakan opsi ini saat Anda ingin mengubah kebijakan penanganan kesalahan default untuk semua instans SafeInt kelas dalam kode Anda.

Catatan

Kelas yang dikustomisasi yang menangani kesalahan dari pustaka SafeInt tidak boleh mengembalikan kontrol ke kode yang disebut penangan kesalahan. Setelah handler kesalahan dipanggil, hasil SafeInt operasi tidak dapat dipercaya.

Hierarki Warisan

SafeInt

Persyaratan

Header: SafeInt.hpp

Catatan

Versi terbaru pustaka ini terletak di https://github.com/dcleblanc/SafeInt. Kloning pustaka dan sertakan SafeInt.hpp untuk menggunakan pustaka SafeInt. Lebih suka repositori GitHub ini ke <safeint.h>. ini adalah versi modern safeint.h <> yang mencakup sejumlah kecil perbaikan bug, menggunakan fitur modern C++ yang menghasilkan kode yang lebih efisien, dan portabel ke platform apa pun menggunakan kompilator gcc, clang, atau Intel.

Contoh

#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.
}

Namespace: tidak ada

SafeInt::SafeInt

Membuat SafeInt objek.

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)

Parameter

i
[di] Nilai untuk objek baru SafeInt . Ini harus berupa parameter jenis T atau U, tergantung pada konstruktor.

b
[di] Nilai Boolean untuk objek baru SafeInt .

u
[di] SafeInt Jenis U. Objek baru SafeInt akan memiliki nilai yang sama dengan u, tetapi akan berjenis T.

U Jenis data yang disimpan di SafeInt. Ini bisa berupa jenis Boolean, karakter, atau bilangan bulat. Jika jenis bilangan bulat, itu dapat ditandatangani atau tidak ditandatangani dan antara 8 dan 64 bit.

Keterangan

Parameter input untuk konstruktor, i atau u, harus berupa jenis Boolean, karakter, atau bilangan bulat. Jika ini adalah jenis parameter lain, SafeInt kelas memanggil static_assert untuk menunjukkan parameter input yang tidak valid.

Konstruktor yang menggunakan jenis U templat secara otomatis mengonversi parameter input ke jenis yang ditentukan oleh T. Kelas SafeInt mengonversi data tanpa kehilangan data. Ini melaporkan ke handler E kesalahan jika tidak dapat mengonversi data ke jenis T tanpa kehilangan data.

Jika Anda membuat SafeInt dari parameter Boolean, Anda perlu segera menginisialisasi nilai. Anda tidak dapat membuat SafeInt menggunakan kode SafeInt<bool> sb;. Ini akan menghasilkan kesalahan kompilasi.