C tidak memiliki tipe boolean bawaan. Apa cara terbaik untuk menggunakannya di C?
C tidak memiliki tipe boolean bawaan. Apa cara terbaik untuk menggunakannya di C?
Jawaban:
Dari yang terbaik menjadi lebih buruk:
Opsi 1 (C99)
#include <stdbool.h>
pilihan 2
typedef enum { false, true } bool;
Opsi 3
typedef int bool;
enum { false, true };
Opsi 4
typedef int bool;
#define true 1
#define false 0
Jika Anda ragu-ragu, lanjutkan dengan # 1!
<stdbool.h>
bool
kompiler yang dipilih mungkin lebih cocok untuk tujuan yang diinginkan dari nilai boolean daripada menggunakan int
(yaitu kompiler dapat memilih untuk mengimplementasikan yang bool
berbeda dari pada int
). Mungkin juga menghasilkan pengecekan tipe yang lebih ketat pada waktu kompilasi, jika Anda beruntung.
int
untuk bool
? Itu sia-sia. Gunakan unsigned char
. Atau menggunakan C builtin _Bool
.
Beberapa pemikiran tentang boolean di C:
Saya cukup tua sehingga saya hanya menggunakan int
s polos sebagai tipe boolean saya tanpa typedefs atau definisi khusus atau enums untuk nilai benar / salah. Jika Anda mengikuti saran saya di bawah ini untuk tidak pernah membandingkan terhadap konstanta boolean, maka Anda hanya perlu menggunakan 0/1 untuk menginisialisasi flag. Namun, pendekatan semacam itu mungkin dianggap terlalu reaksioner di zaman modern ini. Dalam hal ini, seseorang harus menggunakan <stdbool.h>
karena setidaknya memiliki manfaat standar.
Apa pun yang disebut konstanta boolean, gunakan hanya untuk inisialisasi. Jangan pernah menulis sesuatu seperti itu
if (ready == TRUE) ...
while (empty == FALSE) ...
Ini selalu bisa diganti dengan yang lebih jelas
if (ready) ...
while (!empty) ...
Perhatikan bahwa ini sebenarnya dapat secara wajar dan dimengerti dibaca dengan keras.
Beri nama positif variabel boolean Anda, yaitu full
sebagai ganti notfull
. Yang terakhir mengarah ke kode yang sulit dibaca dengan mudah. Membandingkan
if (full) ...
if (!full) ...
dengan
if (!notfull) ...
if (notfull) ...
Kedua mantan pasangan membaca secara alami, sementara !notfull
canggung membaca bahkan seperti apa adanya, dan menjadi jauh lebih buruk dalam ekspresi boolean yang lebih kompleks.
Argumen Boolean umumnya harus dihindari. Pertimbangkan fungsi yang didefinisikan seperti ini
void foo(bool option) { ... }
Dalam tubuh fungsi, sangat jelas apa artinya argumen karena memiliki nama yang nyaman, dan mudah-mudahan bermakna. Tapi, situs panggilan terlihat seperti
foo(TRUE);
foo(FALSE):
Di sini, pada dasarnya tidak mungkin untuk mengatakan apa arti parameter tanpa selalu melihat definisi fungsi atau deklarasi, dan akan menjadi lebih buruk segera jika Anda menambahkan lebih banyak parameter boolean. Saya sarankan juga
typedef enum { OPT_ON, OPT_OFF } foo_option;
void foo(foo_option option);
atau
#define OPT_ON true
#define OPT_OFF false
void foo(bool option) { ... }
Dalam kedua kasus, situs panggilan sekarang terlihat seperti
foo(OPT_ON);
foo(OPT_OFF);
dimana pembaca setidaknya memiliki kesempatan untuk memahami tanpa mengeruk definisi foo
.
a == b
berhasil?
a
dan b
menghitung dari nol, saya akan merekomendasikan a > 0 == b > 0
. Jika Anda bersikeras untuk mengambil keuntungan dari kebenaran nilai bukan nol yang sewenang-wenang, !!var
menghasilkan nilai boolean 0/1 yang setara dengan var
, sehingga Anda bisa menulis !!a == !!b
, meskipun beberapa pembaca akan menganggapnya membingungkan.
!a == !b
juga cukup untuk menguji kesetaraan, bukan nol menjadi nol, dan nol menjadi satu.
!!a
"konversi non-boolean ke nilai kebenaran yang setara", sedangkan saya akan membaca !a
"secara logis membalikkan variabel boolean a". Secara khusus, saya akan mencari beberapa alasan spesifik inversi logis diinginkan.
Boolean dalam C adalah integer: nol untuk false dan non-nol untuk true.
Lihat juga tipe data Boolean , bagian C, C ++, Objective-C, AWK .
Ini adalah versi yang saya gunakan:
typedef enum { false = 0, true = !false } bool;
Karena false hanya memiliki satu nilai, tetapi true logis dapat memiliki banyak nilai, tetapi teknik menetapkan true menjadi apa yang akan digunakan oleh kompiler untuk kebalikan dari false.
Ini menangani masalah seseorang yang mengkode sesuatu yang akan menjadi seperti ini:
if (true == !false)
Saya pikir kita semua akan setuju bahwa itu bukan praktik yang baik, tetapi untuk satu kali biaya melakukan "true =! False" kita menghilangkan masalah itu.
[EDIT] Pada akhirnya saya menggunakan:
typedef enum { myfalse = 0, mytrue = !myfalse } mybool;
untuk menghindari tabrakan nama dengan skema lain yang mendefinisikan true
danfalse
. Namun konsepnya tetap sama.
[EDIT] Untuk menampilkan konversi integer ke boolean:
mybool somebool;
int someint = 5;
somebool = !!someint;
Yang pertama (paling kanan)! mengkonversi bilangan nol ke nol, kemudian bilangan bulat kedua (paling kiri)! mengkonversi 0 ke amyfalse
nilai. Saya akan meninggalkannya sebagai latihan bagi pembaca untuk mengkonversi bilangan bulat nol.
[EDIT] Ini adalah gaya saya untuk menggunakan pengaturan eksplisit dari nilai dalam enum ketika nilai spesifik diperlukan bahkan jika nilai defaultnya akan sama. Contoh: Karena false harus nol saya gunakan false = 0,
daripadafalse,
true
, false
dan bool
disorot di sebagian besar IDE karena mereka adalah nilai enum dan typedef, sebagai lawan dari #defines
, yang jarang disorot oleh sintaks.
gcc -ansi -pedantic -Wall
tidak memberikan peringatan, jadi saya percaya gcc
; Jika ini berhasil bahkan untuk c89
itu harus bekerja c99
juga.
!
hanya dapat mengembalikan nilai 0
dan 1
, jadi true = !false
akan selalu memberikan nilai 1. Metode ini tidak memberikan keamanan ekstra typedef enum { false, true } bool;
.
if(!value)
), tetapi pengecualian itu tidak berlaku dalam kasus khusus ini.
Jika Anda menggunakan kompiler C99, ia memiliki dukungan bawaan untuk tipe bool:
#include <stdbool.h>
int main()
{
bool b = false;
b = true;
}
Hal pertama yang pertama. C, yaitu ISO / IEC 9899 telah memiliki tipe boolean selama 19 tahun sekarang . Itu adalah waktu yang jauh lebih lama daripada yang diharapkan dari karir pemrograman C dengan bagian-bagian amatir / akademik / profesional digabungkan ketika mengunjungi pertanyaan ini . Milik saya memang melampaui itu mungkin hanya 1-2 tahun. Ini berarti bahwa selama waktu rata-rata pembaca telah belajar apa pun tentang C, C sebenarnya telah memiliki tipe data boolean .
Untuk tipe data #include <stdbool.h>
,, dan gunakan true
, false
dan bool
. Atau jangan memasukkannya, dan gunakan _Bool
, 1
dan 0
sebagai gantinya.
Ada berbagai praktik berbahaya yang dipromosikan dalam jawaban lain untuk utas ini. Saya akan mengatasinya:
typedef int bool;
#define true 1
#define false 0
Ini tidak-tidak, karena pembaca biasa - yang memang belajar C dalam 19 tahun itu - akan mengharapkan yang bool
mengacu pada tipe data aktual bool
dan akan berperilaku sama, tetapi tidak! Sebagai contoh
double a = ...;
bool b = a;
Dengan C99 bool
/ _Bool
, b
akan diatur ke false
iff a
adalah nol, dan true
sebaliknya. C11 6.3.1.2p1
- Ketika nilai skalar apa pun dikonversi menjadi
_Bool
, hasilnya adalah 0 jika nilainya sebanding dengan 0; jika tidak, hasilnya adalah 1. 59)Catatan kaki
59) NaNs tidak membandingkan sama dengan 0 dan dengan demikian dikonversi ke 1.
Dengan typedef
di tempat, double
akan dipaksa ke int
- jika nilai ganda tidak dalam kisaranint
, perilaku tidak terdefinisi .
Secara alami hal yang sama berlaku untuk if true
dan false
dinyatakan dalamenum
.
Apa yang lebih berbahaya adalah menyatakan
typedef enum bool {
false, true
} bool;
karena sekarang semua nilai selain 1 dan 0 tidak valid, dan jika nilai seperti itu diberikan ke variabel jenis itu, perilaku akan sepenuhnya tidak terdefinisi .
Karena itu jika Anda tidak dapat menggunakan C99 karena alasan yang tidak dapat dijelaskan, untuk variabel boolean Anda harus menggunakan:
int
dan nilai 0
dan1
apa adanya ; dan hati-hati lakukan konversi domain dari nilai-nilai lain ke ini dengan negasi ganda!!
BOOL
, TRUE
dan FALSE
!int
atau unsigned int
untuk menahan enumerasi, tetapi saya tidak tahu apa-apa dalam Standar yang akan menyebabkan enumerasi berperilaku sebagai selain integer Tipe.
typedef enum {
false = 0,
true
} t_bool;
!0 = 1
oleh standar C, dan !a = 0
untuk nilai bukan nol dari a
. Masalahnya adalah bahwa setiap non-nol dianggap benar. Jadi jika a
dan b
keduanya "benar", itu tidak selalu berarti `a == b`.
C memiliki tipe boolean: bool (setidaknya selama 10 (!) Tahun terakhir)
Sertakan stdbool.h dan true / false akan berfungsi seperti yang diharapkan.
bool
harus makro yang diperluas _Bool
. Perbedaannya penting karena Anda bisa #undef
makro (dan itu diizinkan, setidaknya sebagai ukuran transisi), tetapi Anda tidak untypedef
bisa mengetik. Itu tidak mengubah dorongan utama dari komentar pertama Anda.
Apa pun yang bukan nol dievaluasi benar dalam operasi boolean, jadi Anda bisa saja
#define TRUE 1
#define FALSE 0
dan gunakan konstanta.
Hanya pelengkap jawaban lain dan klarifikasi, jika Anda diizinkan menggunakan C99.
+-------+----------------+-------------------------+--------------------+
| Name | Characteristic | Dependence in stdbool.h | Value |
+-------+----------------+-------------------------+--------------------+
| _Bool | Native type | Don't need header | |
+-------+----------------+-------------------------+--------------------+
| bool | Macro | Yes | Translate to _Bool |
+-------+----------------+-------------------------+--------------------+
| true | Macro | Yes | Translate to 1 |
+-------+----------------+-------------------------+--------------------+
| false | Macro | Yes | Translate to 0 |
+-------+----------------+-------------------------+--------------------+
Beberapa preferensi saya:
_Bool
atau bool
? Keduanya baik-baik saja, tetapi bool
terlihat lebih baik daripada kata kunci_Bool
.bool
dan _Bool
adalah: false
atau true
. Menetapkan 0
atau 1
bukannya false
atau true
valid, tetapi lebih sulit untuk membaca dan memahami aliran logika.Beberapa info dari standar:
_Bool
TIDAK unsigned int
, tetapi merupakan bagian dari grup tipe integer yang tidak ditandai . Cukup besar untuk menampung nilai 0
atau1
.bool
true
danfalse
tetapi tentu saja itu bukan ide yang baik. Kemampuan ini dianggap usang dan akan dihapus di masa depan._Bool
atau bool
, jika nilai skalar sama 0
atau membandingkannya dengan 0
itu 0
, jika tidak hasilnya adalah 1
: _Bool x = 9;
9
dikonversi menjadi 1
ketika ditugaskan x
._Bool
adalah 1 byte (8 bit), biasanya programmer tergoda untuk mencoba menggunakan bit lainnya, tetapi tidak disarankan, karena satu-satunya jaminan yang diberikan adalah bahwa hanya satu bit yang digunakan untuk menyimpan data, tidak seperti tipe char
yang memiliki 8 bit tersedia.Anda dapat menggunakan arang, atau wadah nomor kecil lainnya untuknya.
Kode semu
#define TRUE 1
#define FALSE 0
char bValue = TRUE;
int
), karena pada beberapa arsitektur Anda mendapatkan hasil kinerja yang signifikan karena harus membongkar / menutupi pemeriksaan pada variabel-variabel ini.
Anda bisa menggunakan _Bool, tetapi nilai balik harus berupa bilangan bulat (1 untuk true, 0 untuk false). Namun, disarankan untuk memasukkan dan menggunakan bool seperti dalam C ++, seperti yang dikatakan dalam balasan ini dari forum daniweb , serta jawaban ini , dari pertanyaan stackoverflow lainnya:
_Bool: tipe boolean C99. Menggunakan _Bool secara langsung hanya disarankan jika Anda mempertahankan kode lawas yang sudah mendefinisikan makro untuk bool, true, atau false. Kalau tidak, makro-makro itu distandarkan di header. Sertakan header itu dan Anda dapat menggunakan bool seperti yang Anda lakukan di C ++.
Ekspresi bersyarat dianggap benar jika tidak nol, tetapi standar C mengharuskan operator logika itu sendiri mengembalikan 0 atau 1.
@Tom: #define TRUE! FALSE buruk dan sama sekali tidak ada gunanya. Jika file header masuk ke kode C ++ yang dikompilasi, maka itu dapat menyebabkan masalah:
void foo(bool flag);
...
int flag = TRUE;
foo(flag);
Beberapa kompiler akan menghasilkan peringatan tentang konversi bool int =>. Terkadang orang menghindari ini dengan melakukan:
foo(flag == TRUE);
untuk memaksa ekspresi menjadi bool C ++. Tetapi jika Anda #menentukan BENAR! SALAH, Anda berakhir dengan:
foo(flag == !0);
yang akhirnya melakukan perbandingan int-to-bool yang dapat memicu peringatan itu.
Jika Anda menggunakan C99 maka Anda dapat menggunakan _Bool
jenisnya. Tidak #include
perlu. Anda perlu memperlakukannya seperti integer, meskipun, di mana 1
adalah true
dan 0
adalahfalse
.
Anda kemudian dapat mendefinisikan TRUE
dan FALSE
.
_Bool this_is_a_Boolean_var = 1;
//or using it with true and false
#define TRUE 1
#define FALSE 0
_Bool var = TRUE;
#include <stdbool.h>
dan penggunaan bool
, true
dan false
seperti standar ingin Anda.
Inilah yang saya gunakan:
enum {false, true};
typedef _Bool bool;
_Bool
adalah tipe bawaan C. Ini dimaksudkan untuk nilai boolean.
Anda cukup menggunakan #define
arahan sebagai berikut:
#define TRUE 1
#define FALSE 0
#define NOT(arg) (arg == TRUE)? FALSE : TRUE
typedef int bool;
Dan gunakan sebagai berikut:
bool isVisible = FALSE;
bool isWorking = TRUE;
isVisible = NOT(isVisible);
dan seterusnya
arg
dan ekspresi secara keseluruhan: #define NOT(arg) (((arg) == TRUE) ? FALSE : TRUE)
. Namun, akan lebih baik untuk menguji kepalsuan (itu akan memberikan jawaban yang benar bahkan jika arg
itu 23 bukannya 0 atau 1:. #define NOT(arg) (((arg) == FALSE) ? TRUE : FALSE)
Tetapi seluruh ekspresi dapat dikurangi menjadi #define NOT(arg) (!(arg))
, tentu saja, yang menghasilkan hasil yang sama.