Saya baru saja masuk ke proyek dengan basis kode yang cukup besar.
Saya kebanyakan berurusan dengan C ++ dan banyak kode yang mereka tulis menggunakan negasi ganda untuk logika boolean mereka.
if (!!variable && (!!api.lookup("some-string"))) {
do_some_stuff();
}
Saya tahu orang-orang ini adalah pemrogram yang cerdas, jelas mereka tidak melakukan ini secara tidak sengaja.
Saya bukan ahli C ++ berpengalaman, satu-satunya dugaan saya mengapa mereka melakukan ini adalah bahwa mereka ingin memastikan bahwa nilai yang dievaluasi adalah representasi boolean yang sebenarnya. Jadi mereka meniadakannya, lalu meniadakannya lagi untuk mengembalikannya ke nilai boolean aslinya.
Apakah ini benar, atau saya melewatkan sesuatu?
Jawaban:
Ini adalah trik untuk mengubahnya menjadi bool.
sumber
bool
tipe, untuk membantu menghindari menyimpan nilai selain1
dan0
dalam variabel boolean.!!
atau!=0
memecahkan masalah, dan di antara keduanya saya menemukan pembersih sebelumnya (karena ini akan bekerja pada lebih banyak jenis). Saya juga setuju bahwa tidak ada alasan untuk menggunakan salah satu dari kode tersebut.Ini sebenarnya adalah idiom yang sangat berguna dalam beberapa konteks. Ambil makro ini (contoh dari kernel Linux). Untuk GCC, penerapannya sebagai berikut:
Mengapa mereka harus melakukan ini? GCC
__builtin_expect
memperlakukan parameternya sebagailong
dan tidakbool
, jadi perlu ada beberapa bentuk konversi. Karena mereka tidak tahu apacond
itu saat mereka menulis makro tersebut, yang paling umum adalah menggunakan!!
idiom.Mereka mungkin dapat melakukan hal yang sama dengan membandingkannya dengan 0, tetapi menurut saya, sebenarnya lebih mudah untuk melakukan negasi ganda, karena itulah yang paling dekat dengan cast-to-bool yang dimiliki C.
Kode ini dapat digunakan di C ++ juga ... ini adalah penyebut yang paling rendah. Jika memungkinkan, lakukan apa yang berhasil di C dan C ++.
sumber
Para pembuat kode berpikir bahwa itu akan mengubah operan menjadi bool, tetapi karena operan && sudah secara implisit diubah menjadi bool, itu benar-benar berlebihan.
sumber
Ini adalah teknik untuk menghindari penulisan (variabel! = 0) - yaitu untuk mengubah dari jenis apa pun itu menjadi bool.
Kode IMO seperti ini tidak memiliki tempat dalam sistem yang perlu dijaga - karena ini bukan kode yang langsung dapat dibaca (oleh karena itu pertanyaannya di tempat pertama).
Kode harus dapat dibaca - jika tidak, Anda meninggalkan warisan hutang waktu untuk masa depan - karena diperlukan waktu untuk memahami sesuatu yang berbelit-belit.
sumber
bool(expr)
: ia melakukan hal yang benar dan semua orang memahami maksudnya pada pandangan pertama.!!(expr)
adalah negasi ganda, yang secara tidak sengaja diubah menjadi bool ... ini tidak sederhana.Ya itu benar dan tidak, Anda tidak melewatkan sesuatu.
!!
adalah konversi ke bool. Lihat pertanyaan ini untuk pembahasan lebih lanjut.sumber
Ini mengesampingkan peringatan compiler. Coba ini:
Baris 'bar' menghasilkan "nilai paksa ke bool 'true' atau 'false' (peringatan kinerja)" di MSVC ++, tetapi baris 'baz' menyelinap melalui denda.
sumber
bool
tipenya - semuanya dikodekan sebagai0
atau1
dalam fileint
.Apakah operator! kelebihan beban?
Jika tidak, mereka mungkin melakukan ini untuk mengubah variabel menjadi bool tanpa menghasilkan peringatan. Ini jelas bukan cara standar dalam melakukan sesuatu.
sumber
Legacy C pengembang tidak punya tipe Boolean, sehingga mereka sering
#define TRUE 1
dan#define FALSE 0
kemudian digunakan sewenang-wenang jenis data numerik untuk perbandingan Boolean. Sekarang yang kita milikibool
, banyak kompiler akan mengeluarkan peringatan ketika beberapa tipe tugas dan perbandingan dibuat menggunakan campuran tipe numerik dan tipe Boolean. Kedua penggunaan ini pada akhirnya akan bertabrakan saat bekerja dengan kode lama.Untuk mengatasi masalah ini, beberapa pengembang menggunakan identitas Boolean berikut:
!num_value
returnbool true
ifnum_value == 0
;false
jika tidak.!!num_value
kembalibool false
jikanum_value == 0
;true
jika tidak. Negasi tunggal sudah cukup untuk diubahnum_value
menjadibool
; namun, negasi ganda diperlukan untuk mengembalikan pengertian asli dari ekspresi Boolean.Pola ini dikenal sebagai idiom , yaitu sesuatu yang biasa digunakan oleh orang yang mengenal bahasa tersebut. Oleh karena itu, saya tidak melihatnya sebagai anti-pola, sebanyak yang saya inginkan
static_cast<bool>(num_value)
. Pemeran mungkin memberikan hasil yang benar dengan baik, tetapi beberapa kompiler kemudian mengeluarkan peringatan kinerja, jadi Anda masih harus mengatasinya.Cara lain untuk mengatasi hal ini adalah dengan mengatakan
(num_value != FALSE)
,. Saya baik-baik saja dengan itu juga, tetapi secara keseluruhan,!!num_value
jauh lebih tidak bertele-tele, mungkin lebih jelas, dan tidak membingungkan untuk kedua kalinya Anda melihatnya.sumber
!!
digunakan untuk mengatasi C ++ asli yang tidak memiliki tipe boolean (seperti halnya C).Contoh Soal:
Di dalam
if(condition)
,condition
kebutuhan untuk mengevaluasi beberapa jenis sepertidouble, int, void*
, dll, tetapi tidakbool
karena belum ada.Misalnya ada kelas
int256
(bilangan bulat 256 bit) dan semua konversi / pemeran bilangan bulat kelebihan beban.Untuk menguji apakah
x
itu "benar" atau bukan nol,if (x)
akan mengonversix
ke beberapa bilangan bulat dan kemudian menilai apakahint
itu bukan nol. Kelebihan beban khas(int) x
hanya akan mengembalikan LSbit darix
.if (x)
kemudian hanya menguji LSbits darix
.Tetapi C ++ memiliki
!
operator. Sebuah kelebihan beban!x
biasanya akan mengevaluasi semua bitx
. Jadi untuk kembali ke logika non-terbalikif (!!x)
digunakan.Ref Apakah versi C ++ yang lebih lama menggunakan operator `int` dari sebuah kelas saat mengevaluasi kondisi dalam pernyataan` if () `?
sumber
Seperti yang disebutkan Marcin , mungkin penting jika operator kelebihan beban sedang bermain. Jika tidak, di C / C ++ tidak masalah kecuali jika Anda melakukan salah satu hal berikut:
perbandingan langsung dengan
true
(atau dalam C sesuatu sepertiTRUE
makro), yang hampir selalu merupakan ide yang buruk. Sebagai contoh:if (api.lookup("some-string") == true) {...}
Anda hanya ingin sesuatu diubah menjadi nilai 0/1 yang ketat. Dalam C ++ sebuah penugasan ke a
bool
akan melakukan ini secara implisit (untuk hal-hal yang secara implisit dapat dikonversibool
). Di C atau jika Anda berurusan dengan variabel non-bool, ini adalah idiom yang pernah saya lihat, tapi saya sendiri lebih suka(some_variable != 0)
variasinya.Saya pikir dalam konteks ekspresi boolean yang lebih besar itu hanya mengacaukan segalanya.
sumber
Jika variabel berjenis objek, variabel itu mungkin memiliki a! ditentukan oleh operator tetapi tidak ada transmisi ke bool (atau lebih buruk lagi, transmisi implisit ke int dengan semantik berbeda. Memanggil! operator dua kali menghasilkan konversi ke bool yang berfungsi bahkan dalam kasus yang aneh.
sumber
Itu benar tetapi, di C, tidak ada gunanya di sini - 'jika' dan '&&' akan memperlakukan ekspresi tersebut dengan cara yang sama tanpa '!!'.
Alasan untuk melakukan ini di C ++, saya kira, adalah bahwa '&&' bisa jadi kelebihan beban. Tapi kemudian, begitu juga '!', Jadi tidak benar - benar menjamin Anda mendapatkan bool, tanpa melihat kode untuk jenis
variable
danapi.call
. Mungkin seseorang dengan lebih banyak pengalaman C ++ bisa menjelaskan; mungkin itu dimaksudkan sebagai semacam ukuran pertahanan mendalam, bukan jaminan.sumber
if
atau&&
, tetapi penggunaan!!
mungkin membantu pada beberapa kompiler jikaif (!!(number & mask))
diganti denganbit triggered = !!(number & mask); if (triggered)
; pada beberapa kompiler tertanam dengan tipe bit, menugaskan misalnya 256 ke tipe bit akan menghasilkan nol. Tanpa!!
, transformasi yang tampaknya aman (menyalinif
kondisi ke variabel dan kemudian bercabang) tidak akan aman.Mungkin programmernya memikirkan hal seperti ini ...
!! myAnswer adalah boolean. Dalam konteksnya, itu harus menjadi boolean, tapi saya hanya suka bang bang untuk memastikan, karena suatu ketika ada bug misterius yang menggigit saya, dan bang bang, saya membunuhnya.
sumber
Ini mungkin contoh dari trik double-bang , lihat The Safe Bool Idiom untuk lebih jelasnya. Di sini saya merangkum halaman pertama artikel.
Di C ++ ada beberapa cara untuk menyediakan pengujian Boolean untuk kelas.
Kita bisa menguji kelasnya,
Namun,
opereator bool
dianggap tidak aman karena memungkinkan operasi yang tidak masuk akal sepertitest << 1;
atauint i=test
.Implementasinya sepele,
Dua cara idiomatik untuk menguji
Testable
objek adalahVersi pertama
if (!!test)
adalah apa yang oleh sebagian orang disebut sebagai trik double-bang .sumber
explicit operator bool
untuk mencegah konversi implisit ke tipe integral lainnya.