Kita tahu bahwa bilangan apa pun yang tidak sama 0
dipandang seperti true
di C, jadi kita bisa menulis:
int a = 16;
while (a--)
printf("%d\n", a); // prints numbers from 15 to 0
Namun, saya bertanya-tanya apakah benar / salah didefinisikan sebagai 1
/ 0
dalam C, jadi saya mencoba kode di bawah ini:
printf("True = %d, False = %d\n", (0 == 0), (0 != 0)); // prints: True = 1, False = 0
Apakah standar C secara eksplisit menunjukkan nilai kebenaran benar dan salah sebagai 1
dan 0
masing - masing?
gcc
dengan-std=c89
dan menghasilkan hasil yang sama.Jawaban:
Standar C mendefinisikan
true
danfalse
sebagai makrostdbool.h
yang diperluas menjadi1
dan0
masing - masing.C11-§7.18:
Untuk operator
==
dan!=
, kata standarC11-§6.5.9 / 3:
sumber
0 == 0
dan0 != 0
lain - lain, bukan nilai makro.true
dia maksud adalah "nilai perbandingan yang benar" atau sesuatu, bukan makrotrue
ctrl
+f
;)NaN == NaN
salah danNaN != NaN
benar. Tidak ada masalah dengan pernyataan itu.Ini tidak secara eksplisit ditunjukkan dalam C11. Semua operasi tingkat bahasa akan mengembalikan 1 sebagai benar (dan menerima apa pun yang bukan nol termasuk NaN sebagai benar).
_Bool
, maka benar harus 1 karena standar hanya mengharuskannya untuk menampung 0 dan 1. (§6.2.5 / 2).<stdbool.h>
makrotrue
meluas ke1
(§7.18 / 3)==
,!=
,<
,>
,<=
Dan>=
kembali 0 atau 1 (§6.5.8 / 6, §6.5.9 / 3).!
,&&
dan||
mengembalikan 0 atau 1 (§6.5.3.3 / 5, §6.5.13 / 3, §6.5.14 / 3)defined
meluas ke 0 atau 1 (§6.10.1 / 1)Tetapi semua fungsi pustaka standar misalnya
islower
katakan saja "bukan nol" untuk kebenaran (misalnya §7.4.1 / 1, §7.17.5.1 / 3, §7.30.2.1 / 1, §7.30.2.2.1 / 4).sumber
Ada dua area standar yang perlu Anda waspadai ketika berhadapan dengan nilai Boolean (maksud saya nilai benar / salah daripada
bool/_Bool
tipe C tertentu ) di C.Yang pertama berkaitan dengan hasil ekspresi dan dapat ditemukan di berbagai bagian
C11 6.5 Expressions
(operator relasional dan persamaan, misalnya). Intinya adalah, setiap kali nilai Boolean dihasilkan oleh ekspresi, itu ...Jadi, ya, hasil dari ekspresi yang menghasilkan Boolean akan menjadi satu untuk benar, atau nol untuk salah. Ini cocok dengan apa yang akan Anda temukan di
stdbool.h
mana makro standartrue
danfalse
ditentukan dengan cara yang sama.Namun perlu diingat bahwa, mengikuti prinsip ketahanan "jadilah konservatif dalam apa yang Anda kirim, liberal dalam apa yang Anda terima", interpretasi bilangan bulat dalam konteks Boolean agak lebih santai.
Sekali lagi, dari berbagai bagian
6.5
, Anda akan melihat bahasa seperti:Dari (dan bagian lain), sudah jelas bahwa nol dianggap palsu dan setiap nilai lain benar.
Selain itu, bahasa yang menentukan nilai apa yang digunakan untuk pembangkitan dan interpretasi Boolean juga muncul kembali di C99 dan C89 sehingga mereka sudah ada cukup lama. Bahkan K&R (ANSI-C edisi kedua dan edisi pertama) menetapkan itu, dengan segmen teks seperti:
Makro
stdbool.h
muncul kembali di C99 juga, tetapi tidak di C89 atau K&R karena file header itu tidak ada pada saat itu.sumber
||
,, dll.==
,!=
menghasilkanint
, bukan tipe booleanif
,while
,for
, dll, 'true' hanya berarti 'non-nol'." Ini adalah bagian terpenting dari jawabannya dan, menurut saya, merupakan pilihan yang disayangkan dari Dennis Ritchie sejak dulu. Siapapun yang memiliki fungsi tertulis yang mengembalikan kode kesalahan sebagai nilai kembali umumnya memiliki#define noErr 0
dan kode kesalahan bukan nol adalah kesalahan. Dan masalahnya adalah kesederhanaan dan keindahanif ( ready_to_do_something() ){do_something();}
tidak berhasil. Itu harusif ( !not_ready_to_do_something() ){do_something();}
"Ada banyak kebohongan, tapi hanya satu kebenaran." BENAR harus 0.A.7.6/7/10/11
(relasional / persamaan / logika-dan / logika-atau) semua menentukan bahwa itu memberikan 0 atau 1 sebagai hasil. Telah memperbarui jawaban untuk memasukkan itu.Anda mencampurkan banyak hal yang berbeda: pernyataan kontrol, operator, dan tipe boolean. Masing-masing memiliki aturannya sendiri.
Pernyataan kontrol berfungsi seperti misalnya
if
pernyataan, C11 6.4.8.1:while
,for
dll memiliki aturan yang sama. Ini tidak ada hubungannya dengan "benar" atau "salah".Adapun operator yang seharusnya menghasilkan hasil boolean, mereka sebenarnya menghasilkan
int
dengan nilai 1 atau 0. Sebagai contoh operator persamaan, C11 6.5.9:Semua hal di atas adalah karena C tidak memiliki tipe boolean sampai tahun 1999, dan bahkan ketika sudah mendapatkannya, aturan di atas tidak berubah. Jadi tidak seperti kebanyakan bahasa pemrograman lain di mana pernyataan dan operator menghasilkan tipe boolean (seperti C ++ dan Java), mereka hanya menghasilkan
int
, dengan nilai nol atau bukan nol. Misalnya,sizeof(1==1)
akan memberikan 4 di C tetapi 1 di C ++.Tipe boolean sebenarnya di C diberi nama
_Bool
dan membutuhkan kompiler modern. Headerstdbool.h
mendefinisikan makrobool
,true
danfalse
, yang diperluas menjadi_Bool
,1
dan0
masing - masing (untuk kompatibilitas dengan C ++).Namun hal ini dianggap sebagai praktik pemrograman yang baik untuk memperlakukan pernyataan kontrol dan operator seolah-olah mereka benar-benar membutuhkan / menghasilkan tipe boolean. Standar pengkodean tertentu seperti MISRA-C merekomendasikan praktik semacam itu. Itu adalah:
if(ptr == NULL)
dari padaif(ptr)
.if((data & mask) != 0)
dari padaif(data & mask)
.Tujuan dari gaya tersebut adalah untuk meningkatkan keamanan tipe dengan bantuan alat analisis statis, yang pada gilirannya mengurangi bug. Bisa dibilang, gaya ini hanya bermakna jika Anda memang menggunakan penganalisis statis. Meskipun dalam beberapa kasus, ini mengarah ke kode yang lebih mudah dibaca dan terdokumentasi sendiri, misalnya
if(c == '\0')
Bagus, maksudnya jelas, kodenya mendokumentasikan sendiri.
melawan
if(c)
Buruk. Bisa berarti apa saja, dan kita harus mencari tipe
c
untuk memahami kodenya. Apakah itu bilangan bulat, penunjuk atau karakter?sumber
sizeof(bool)
adalah implementasi khusus di C ++. Lihat stackoverflow.com/questions/4897844/is-sizeofbool-defined .if(ptr != NULL)
, atau mungkinif(!ptr)
?if(c == '\0')
cocok untuk kesalahan pengkodean pemula yang sangat umumif(c = '\0')
, jadi saya menghindarinya. Setuju,if(c)
itu buruk ... mestinya, misalnya,if(valveIsOpen)
Saya telah memprogram dalam banyak bahasa. Saya telah melihat true be 1 atau -1 tergantung pada bahasanya. Logika di balik wujud sejati 1 adalah bahwa sedikit adalah 0 atau 1. Logika di balik wujud sejati -1 adalah bahwa! operator adalah pelengkap seseorang. Itu mengubah semua 1 menjadi 0 dan semua 0 menjadi 1 dalam int. Jadi, untuk int,! 0 = -1 dan! (- 1) = 0. Ini telah cukup membuat saya tersandung sehingga saya tidak membandingkan sesuatu menjadi == true, tetapi membandingkannya menjadi! = False. Dengan begitu, gaya pemrograman saya berfungsi di semua bahasa. Jadi jawaban saya adalah jangan khawatir tentang itu, tetapi programlah agar kode Anda berfungsi dengan benar.
sumber
Jawaban ini perlu dilihat lebih dekat.
Definisi sebenarnya di C ++ adalah bahwa apa pun yang bukan 0 akan dianggap benar. Mengapa ini relevan? Karena C ++ tidak tahu apa itu integer dengan cara kita memikirkannya - kita menciptakan makna itu, yang dimilikinya hanyalah shell dan aturan untuk artinya. Ia tahu apa itu bit, yang membentuk sebuah integer.
1 sebagai bilangan bulat direpresentasikan secara longgar dalam bit, katakan int 8-bit ditandatangani sebagai 0000 0001. Seringkali apa yang kita lihat secara visual adalah sedikit kebohongan, -1 adalah cara yang jauh lebih umum untuk merepresentasikannya karena sifatnya yang ditandatangani dari 'integer'. 1 benar-benar tidak bisa berarti benar, mengapa? Karena BUKAN operasinya adalah 1111 1110. Itu masalah yang sangat besar untuk boolean. Ketika kita berbicara tentang boolean, itu hanya 1 bit - sangat sederhana, 0 salah dan 1 benar. Semua operasi logika dianggap sepele. Inilah mengapa '-1' harus ditetapkan sebagai 'true' untuk integer (bertanda tangan). 1111 1111 NOT'ed menjadi 0000 0000 --- logika bertahan dan kami baik-baik saja. Unsigned int sedikit rumit dan lebih umum digunakan di masa lalu - di mana 1 berarti benar karena mudah untuk menyiratkan logika bahwa '
Itulah penjelasannya. Saya mengatakan jawaban yang diterima di sini salah - tidak ada definisi yang jelas dalam definisi C / C ++. Boolean adalah boolean, Anda dapat memperlakukan bilangan bulat sebagai boolean, tetapi fakta bahwa keluarannya adalah bilangan bulat tidak berarti apa pun tentang operasi yang sebenarnya dilakukan adalah bitwise.
sumber
Itu terjadi karena Operator Relasional dalam
printf
pernyataan Anda .Operator
==
dan operator!=
Karena
(0 == 0)
berlaku demikian, hal itu memberi nilai1
Padahal,
(0 != 0)
tidak berlaku begitu, memberi nilai0
.sumber