Saya telah melihat definisi dalam C
#define TRUE (1==1)
#define FALSE (!TRUE)
Apakah ini perlu? Apa manfaatnya dengan mendefinisikan TRUE sebagai 1, dan SALAH sebagai 0?
c
precompiler
Robert Harvey
sumber
sumber
#define TRUE (’/’/’/’)
:;#define FALSE (’-’-’-’)
(diambil dari coding-guidelines.com/cbook/cbook1_1.pdf halaman 871)Jawaban:
Pendekatan ini akan menggunakan
boolean
tipe aktual (dan menyelesaikan ketrue
danfalse
) jika kompiler mendukungnya. (khususnya, C ++)Namun, akan lebih baik untuk memeriksa apakah C ++ sedang digunakan (melalui
__cplusplus
makro) dan benar-benar menggunakantrue
danfalse
.Dalam kompiler C, ini sama dengan
0
dan1
.(perhatikan bahwa menghapus tanda kurung akan merusak karena urutan operasi)
sumber
1==1
adalahint
. (lihat stackoverflow.com/questions/7687403/… .)boolean
tipe?true
ataufalse
.#define TRUE true
dan#define FALSE false
kapan pun__cplusplus
didefinisikan.Jawabannya adalah portabilitas. Nilai numerik
TRUE
danFALSE
tidak penting. Apa yang penting adalah bahwa pernyataan sepertiif (1 < 2)
mengevaluasi keif (TRUE)
dan pernyataan sepertiif (1 > 2)
mengevaluasi keif (FALSE)
.Diberikan, dalam C,
(1 < 2)
mengevaluasi1
dan(1 > 2)
mengevaluasi0
, sehingga seperti yang dikatakan orang lain, tidak ada perbedaan praktis sejauh menyangkut kompiler. Tetapi dengan membiarkan kompiler mendefinisikanTRUE
danFALSE
sesuai dengan aturannya sendiri, Anda membuat maknanya secara eksplisit untuk programmer, dan Anda menjamin konsistensi dalam program Anda dan pustaka lainnya (dengan asumsi pustaka lain mengikuti standar C ... Anda akan terkesima).Some History
Beberapa BASIC didefinisikan
FALSE
sebagai0
danTRUE
sebagai-1
. Seperti banyak bahasa modern, mereka menafsirkan nilai bukan nolTRUE
, tetapi mereka mengevaluasi ekspresi boolean yang benar-1
.NOT
Operasi mereka dilaksanakan dengan menambahkan 1 dan membalik tanda, karena efisien untuk melakukannya dengan cara itu. Jadi 'TIDAK x' menjadi-(x+1)
. Efek samping dari hal ini adalah bahwa nilai suka5
dievaluasiTRUE
, tetapiNOT 5
dievaluasi-6
, yang jugaTRUE
! Menemukan bug semacam ini tidak menyenangkan.Praktik Terbaik
Mengingat de facto aturan yang nol ditafsirkan sebagai
FALSE
dan setiap nilai bukan nol ditafsirkan sebagaiTRUE
, Anda harus tidak pernah membandingkan ekspresi boolean-mencari untukTRUE
atauFALSE
. Contoh:Mengapa? Karena banyak programmer menggunakan cara pintas memperlakukan
int
s sebagaibool
s. Mereka tidak sama, tetapi umumnya kompiler mengizinkannya. Jadi, misalnya, sangat sah untuk menulisItu terlihat sah, dan kompiler akan dengan senang hati menerimanya, tetapi mungkin tidak melakukan apa yang Anda inginkan. Itu karena nilai kembalinya
strcmp()
adalah0 jika
yourString == myString
<0 jika
yourString < myString
> 0 jika
yourString > myString
Jadi baris di atas
TRUE
hanya mengembalikan ketikayourString > myString
.Cara yang tepat untuk melakukan ini adalah baik
atau
Demikian pula:
Anda akan sering menemukan beberapa "contoh buruk" ini dalam kode produksi, dan banyak pemrogram berpengalaman bersumpah dengan mereka: mereka bekerja, ada yang lebih pendek daripada alternatif mereka yang benar (pedantically?), Dan idiom-idiom tersebut hampir dikenal secara universal. Tetapi pertimbangkan: versi "benar" tidak kurang efisien, mereka dijamin portabel, mereka akan lulus bahkan pada tingkat yang paling ketat, dan bahkan pemrogram baru akan memahaminya.
Bukankah itu sepadan?
sumber
(1==1)
tidak lebih portabel daripada1
. Aturan kompiler sendiri adalah dari bahasa C, yang jelas dan tidak ambigu tentang semantik kesetaraan dan operator relasional. Saya belum pernah melihat seorang kompiler membuat kesalahan ini.strcmp
diketahui kurang dari, sama atau lebih besar dari 0. Tidak dijamin menjadi -1, 0 atau 1 dan ada platform di alam bebas yang tidak mengembalikan nilai-nilai itu untuk mendapatkan kecepatan implementasi. Jadi kalaustrcmp(a, b) == TRUE
begitua > b
tetapi implikasi sebaliknya mungkin tidak berlaku.(1==1)
dan1
keduanya merupakan ekspresi tipe konstanint
dengan nilai 1. Keduanya identik secara semantik. Saya kira Anda dapat menulis kode yang melayani pembaca yang tidak tahu itu, tetapi di mana itu berakhir?The
(1 == 1)
Trik ini berguna untuk mendefinisikanTRUE
dengan cara yang transparan untuk C, namun menyediakan mengetik yang lebih baik di C ++. Kode yang sama dapat ditafsirkan sebagai C atau C ++ jika Anda menulis dalam dialek yang disebut "Bersihkan C" (yang mengkompilasi sebagai C atau C ++) atau jika Anda menulis file header API yang dapat digunakan oleh programmer C atau C ++.Dalam unit terjemahan C,
1 == 1
memiliki arti yang sama persis seperti1
; dan1 == 0
memiliki arti yang sama dengan0
. Namun, dalam unit terjemahan C ++,1 == 1
memiliki tipebool
. JadiTRUE
makro didefinisikan dengan cara itu mengintegrasikan lebih baik ke C ++.Contoh bagaimana itu terintegrasi lebih baik adalah bahwa misalnya jika fungsi
foo
memiliki kelebihan untukint
dan untukbool
, makafoo(TRUE)
akan memilihbool
kelebihan. JikaTRUE
hanya didefinisikan sebagai1
, maka itu tidak akan berfungsi dengan baik di C ++.foo(TRUE)
akan menginginkanint
kelebihan.Tentu saja, C99 diperkenalkan
bool
,true
, danfalse
dan ini dapat digunakan di file header yang bekerja dengan C99 dan dengan C.Namun:
TRUE
danFALSE
sebagai(0==0)
dan(1==0)
sebelum C99.Jika Anda bekerja dalam proyek campuran C dan C ++, dan tidak ingin C99, tentukan huruf kecil
true
,false
danbool
sebagai gantinya.Yang sedang berkata,
0==0
trik itu (adalah?) Digunakan oleh beberapa programmer bahkan dalam kode yang tidak pernah dimaksudkan untuk beroperasi dengan C ++ dengan cara apa pun. Itu tidak membeli apa pun dan menunjukkan bahwa programmer memiliki kesalahpahaman tentang cara kerja boolean di C.Jika penjelasan C ++ tidak jelas, berikut ini adalah program uji:
Hasil:
Adapun pertanyaan dari komentar tentang bagaimana kelebihan fungsi C ++ relevan dengan pemrograman campuran C dan C ++. Ini hanya menggambarkan perbedaan tipe. Alasan yang valid untuk menginginkan
true
konstantabool
ketika dikompilasi sebagai C ++ adalah untuk diagnostik yang bersih. Pada tingkat peringatan tertinggi, kompiler C ++ mungkin memperingatkan kita tentang konversi jika kita melewatkan integer sebagaibool
parameter. Salah satu alasan penulisan Clean C bukan hanya karena kode kami lebih portabel (karena dipahami oleh kompiler C ++, tidak hanya kompiler C), tetapi kita dapat mengambil manfaat dari pendapat diagnostik kompiler C ++.sumber
TRUE
akan berbeda di bawah C ++.#ifdef __cplusplus
untuk mengekspresikan maksud Anda dengan lebih jelas.bool
danint
tidak terlalu penting dalam praktik, karena semuanya secara implisit dapat dikonversi satu sama lain (dan dalam C sebenarnya "sama" , catat tanda kutipnya. , meskipun) dan tidak ada banyak situasi di mana Anda benar-benar perlu memisahkan diri di antara keduanya. "tidak banyak" mungkin terlalu berat, "jauh lebih sedikit dibandingkan dengan kode yang menggunakan template dan kelebihan beban" mungkin lebih baik.setara dengan
dalam C.
Hasil dari operator relasional adalah
0
atau1
.1==1
dijamin untuk dievaluasi1
dan!(1==1)
dijamin untuk dievaluasi0
.Sama sekali tidak ada alasan untuk menggunakan formulir pertama. Perhatikan bahwa bentuk pertama tidak kurang efisien karena pada hampir semua kompiler ekspresi konstan dievaluasi pada waktu kompilasi daripada pada saat run-time. Ini diizinkan menurut aturan ini:
PC-Lint bahkan akan mengeluarkan pesan (506, nilai konstan boolean) jika Anda tidak menggunakan literal untuk
TRUE
danFALSE
makro:Juga di C99,
stdbool.h
definisi untuk makro booleantrue
danfalse
langsung menggunakan literal:sumber
1==1
dijamin akan dievaluasi ke1
if(foo == true)
, yang akan berubah dari sekadar praktik buruk menjadi buggy.(x == TRUE)
dapat memiliki nilai kebenaran yang berbeda darix
.Selain C ++ (sudah disebutkan), manfaat lain adalah untuk alat analisis statis. Kompiler akan menghapus semua inefisiensi, tetapi penganalisa statis dapat menggunakan tipe abstraknya sendiri untuk membedakan antara hasil perbandingan dan tipe integer lainnya, sehingga ia mengetahui secara implisit bahwa TRUE harus merupakan hasil perbandingan dan tidak boleh dianggap kompatibel dengan bilangan bulat.
Jelas C mengatakan bahwa mereka kompatibel, tetapi Anda dapat memilih untuk tidak sengaja menggunakan fitur itu untuk membantu menyoroti bug - misalnya, di mana seseorang mungkin bingung
&
dan&&
, atau mereka telah mengacaukan prioritas operator mereka.sumber
if (boolean_var == TRUE)
dengan cara ekspansiif (boolean_var == (1 == 1))
yang berkat info tipe ditingkatkan dari(1 == 1)
node jatuh ke dalam polaif (<*> == <boolean_expr>)
.Perbedaan praktisnya tidak ada.
0
dievaluasi kefalse
dan1
dievaluasi ketrue
. Fakta bahwa Anda menggunakan ekspresi boolean (1 == 1
) atau1
, untuk mendefinisikantrue
, tidak ada bedanya. Keduanya dievaluasiint
.Perhatikan bahwa C library standar menyediakan header khusus untuk mendefinisikan boolean:
stdbool.h
.sumber
true
dievaluasi ke1
danfalse
dievaluasi ke0
. C tidak tahu tentang tipe boolean asli, mereka hanya int.int
, dengan nilai0
atau1
. C memang memiliki tipe boolean yang sebenarnya (_Bool
, dengan makro yangbool
didefinisikan<stdbool.h>
, tetapi itu hanya ditambahkan dalam C99, yang tidak mengubah semantik operator untuk menggunakan tipe baru._Bool
, dan<stdbool.h>
telah#define bool _Bool
.1 == 1
yang dievaluasi sebagaiint
. Diedit.Kami tidak tahu nilai pasti bahwa TRUE sama dengan dan kompiler dapat memiliki definisi sendiri. Jadi apa yang Anda privode adalah menggunakan definisi internal kompiler. Ini tidak selalu diperlukan jika Anda memiliki kebiasaan pemrograman yang baik tetapi dapat menghindari masalah untuk beberapa gaya pengkodean yang buruk, misalnya:
if ((a> b) == BENAR)
Ini bisa menjadi bencana jika Anda mendefinisikan TRUE secara manual sebagai 1, sedangkan nilai internal TRUE adalah nilai lain.
sumber
>
operator selalu menghasilkan 1 untuk true, 0 untuk false. Tidak ada kemungkinan kompiler C mendapatkan kesalahan ini. Perbandingan kesetaraanTRUE
danFALSE
gaya yang buruk; di atas lebih jelas ditulis sebagaiif (a > b)
. Tetapi gagasan bahwa penyusun C yang berbeda dapat memperlakukan kebenaran dan salah secara berbeda sama sekali salah.Biasanya dalam Bahasa Pemrograman C, 1 didefinisikan sebagai benar dan 0 didefinisikan sebagai salah. Karenanya mengapa Anda sering melihat hal berikut:
Namun, angka apa pun yang tidak sama dengan 0 akan dievaluasi menjadi benar juga dalam pernyataan bersyarat. Oleh karena itu dengan menggunakan di bawah ini:
Anda dapat secara eksplisit menunjukkan bahwa Anda mencoba untuk bermain aman dengan membuat kesalahan sama dengan apa pun yang tidak benar.
sumber