C'de boole değerlerini kullanma


Yanıtlar:


1050

En iyiden kötüye:

Seçenek 1 (C99)

#include <stdbool.h>

seçenek 2

typedef enum { false, true } bool;

Seçenek 3

typedef int bool;
enum { false, true };

Seçenek 4

typedef int bool;
#define true 1
#define false 0

açıklama

  • Seçenek 1 yalnızca C99 kullanıyorsanız ve bunu yapmanın "standart yolu" ise çalışır. Mümkünse bunu seçin.
  • Seçenek 2, 3 ve 4 pratikte aynı özdeş davranışa sahip olacaktır. # 2 ve # 3 olsa da #defines kullanmayın, bence daha iyidir.

Kararsızsanız # 1 ile devam edin!


1
Neden en kötü seçeneklerden en iyileri olduklarını açıklayabilir misiniz ?
Endolit

1
hizalama @endolith, optimizasyonlar ve yol saklamak için <stdbool.h> boolderleyici seçer bir kullanan daha Boole değer hedeflenen amaca daha uygun olabilir int(bir uygulamayı tercih edilebilir, yani derleyici boolfarklı bir daha int). Ayrıca, eğer şanslıysanız, derleme zamanında daha katı tip kontrolüne neden olabilir.
blubberdiblub

1
Neden kullanılmalıdır intiçin bool? Bu savurgan. Kullanın unsigned char. Ya da C'nin yerleşikini kullanın _Bool.
user12211554

@NoBody Daha küçük bir tür kullanmak belleğe kaydedebilir, ancak daha hızlı yapamayabilir. Genellikle, daha küçük bir boyut yerine işlemcinin yerel kelime boyutunu kullanmak daha hızlıdır, çünkü derleyicinin düzgün bir şekilde hizalamak için bit kaydırmaları yapmasını gerektirebilir
Ted Klein Bergman

241

C'deki booleans hakkında birkaç düşünce:

Ben intherhangi bir typedefs veya özel tanımlar veya doğru / yanlış değerleri için numaralandırma olmadan boolean türüm olarak yalnızca düz s kullanacak kadar yaşlıyım. Boole sabitleriyle hiçbir zaman karşılaştırma yapma konusunda aşağıdaki önerilerimi uygularsanız, yine de bayrakları başlatmak için yalnızca 0/1 kullanmanız gerekir. Bununla birlikte, böyle bir yaklaşım bu modern zamanlarda çok gerici olarak görülebilir. Bu durumda, <stdbool.h>en azından standardize olma avantajına sahip olduğu için kesinlikle kullanılmalıdır .

Boole sabitleri ne denirse adlandırın, bunları yalnızca başlatma için kullanın. Asla böyle bir şey yazmayın

if (ready == TRUE) ...
while (empty == FALSE) ...

Bunlar her zaman temizleyici ile değiştirilebilir

if (ready) ...
while (!empty) ...

Bunların makul ve anlaşılır bir şekilde yüksek sesle okunabileceğini unutmayın.

Senin boolean değişkenler pozitif isimleri, yani ver fullyerine notfull. İkincisi, kolayca okunması zor olan koda yol açar. Karşılaştırmak

if (full) ...
if (!full) ...

ile

if (!notfull) ...
if (notfull) ...

Eski çiftin her ikisi de doğal olarak okurken, !notfullolduğu gibi okumak zor ve daha karmaşık boole ifadelerinde çok daha kötü hale geliyor.

Boole argümanlarından genellikle kaçınılmalıdır. Bu şekilde tanımlanan bir işlevi düşünün

void foo(bool option) { ... }

Fonksiyonun bünyesinde, argümanın ne anlama geldiği çok açıktır, çünkü uygun ve umarım anlamlı bir isme sahiptir. Ancak, arama siteleri

foo(TRUE);
foo(FALSE):

Burada, parametrenin her zaman işlev tanımına veya bildirimine bakmadan ne anlama geldiğini söylemek imkansızdır ve daha fazla boole parametresi eklerseniz çok daha kötü hale gelir. Ben de öneririm

typedef enum { OPT_ON, OPT_OFF } foo_option;
void foo(foo_option option);

veya

#define OPT_ON true
#define OPT_OFF false
void foo(bool option) { ... }

Her iki durumda da, çağrı sitesi artık

foo(OPT_ON);
foo(OPT_OFF);

okuyucunun tanımını taramadan en azından anlama şansı vardır foo.


1
Eşitlik için iki değişkeni nasıl karşılaştırıyorsunuz? Asla boolean sabitleri kullanmak işe yaramaz, ancak sabit olmayan bir değerle karşılaştırırken sorunu çözmez.
Baruch

Affet beni, ama soruyu anlamıyorum. Eşitlik için iki boole değişkenini nasıl karşılaştırdığımı mı soruyorsunuz? Varsa, çalışmaz a == bmı?
Dale Hagglund

5
@Kenji Söyledikleriniz doğrudur, ancak birinden farklı değerleri true için eşdeğer olarak kullanmanın neredeyse her zaman kötü bir fikir olduğuna inanıyorum. Varsayarak, sizin örnekte Yani ave bsıfırdan saymak, ben tavsiye ederim a > 0 == b > 0yerine. Sıfır olmayan rasgele değerlerin doğruluğundan faydalanmakta ısrar ederseniz !!var, boolean 0/1 değerine eşdeğerdir var, bu nedenle yazabilirsiniz !!a == !!b, ancak birkaç okuyucu kafa karıştırıcı bulacaktır.
Dale Hagglund

3
!a == !beşitliği test etmek için de yeterlidir, sıfır olmayanlar sıfır olur ve sıfırlar bir olur.
ryanpattison

5
@rpattiso Tabii ki haklısın, ama sanırım !!a"boolean olmayan a'yı eşdeğer doğruluk değerine dönüştür !a" olarak okurken , "mantıksal boole değişkenini mantıksal olarak ters çevir" olarak okurdum . Özellikle, mantıksal tersinmenin istendiği belirli bir sebep ararım.
Dale Hagglund


74

İşte kullandığım sürüm:

typedef enum { false = 0, true = !false } bool;

Çünkü yanlış yalnızca bir değere sahiptir, ancak mantıksal bir doğru birçok değere sahip olabilir, ancak teknik derleyicinin yanlışın tersi için kullanacağı şekilde doğrudur.

Bu, aşağıya inecek bir şeyi kodlayan birinin sorununu halleder:

if (true == !false)

Sanırım hepimiz bunun iyi bir uygulama olmadığı konusunda hemfikiriz, ama bir defalık maliyeti için "true =! False" bu sorunu ortadan kaldırıyoruz.

[EDIT] Sonunda kullandım:

typedef enum { myfalse = 0, mytrue = !myfalse } mybool;

tanımlayan diğer şemalarla isim çarpışmasını önlemek trueve false. Ancak konsept aynı kalır.

[EDIT] Tamsayının boole dönüştürmesini göstermek için:

mybool somebool;
int someint = 5;
somebool = !!someint;

İlk (en doğru)! sıfır olmayan tamsayıyı 0'a, sonra ikinciye (en solda) dönüştürür! 0 myfalsedeğerini bir değere dönüştürür . Okuyucunun sıfır tamsayısını dönüştürmesi için bir alıştırma olarak bırakacağım.

[EDIT] Benim tarzım, varsayılan değer aynı olsa bile, belirli bir değer gerektiğinde numaralandırmada bir değerin açık ayarını kullanmaktır. Örnek: Yanlışın sıfır olması gerektiğinden false = 0,,false,


5
Ayrıca çeteleler kullanarak başka avantajı IDE entegrasyonu - true, falseve boolvurgulanır en IDE Hadi onlar yerine enum değerler ve Typedef, çünkü #definesnadiren sözdizimi vurgulanan vardır.

Meraklı: Gerçekten işe yarayıp yaramadığını görmezden gelmek, bir numaralandırmaya aynı numaralandırmada önceki bir değere başvurma izni vermek geçerli mi (99+) ?

@ tgm1024 gcc -ansi -pedantic -Wallhiçbir uyarı vermiyor , bu yüzden güveniyorum gcc; Bu bile c89işe c99yarıyorsa da işe yaramalıdır.
yyny

1
"Çünkü yanlış yalnızca bir değere sahiptir, ancak mantıksal bir gerçek birçok değere sahip olabilir, ancak teknik derleyicinin yanlışın tersi için kullanacağı şekilde doğrudur." Olumsuzlama operatörü !yalnızca değerleri döndürebilir 0ve 1böylece true = !falseher zaman 1 değerini atayacaktır. Bu yöntem fazladan güvenlik sağlamaz typedef enum { false, true } bool;.
user694733

1
Bulduğum ilk şey C90'dan (6.3.3.3 Tekli aritmetik işleçler): "Eğer işleneninin değeri 0 ile eşit değilse, mantıksal olumsuzlama operatörünün! Sonucu 0'dır. 1 sonuç int türüne sahiptir.! E ifadesi (O == E) ile eşdeğerdir. " Bu, standart C'yi desteklediğini iddia eden herhangi bir derleyiciyi kapsamalıdır. Derleyiciler, gözlemlenebilir davranış (örneğin if(!value)) için önemli olmadığı durumlarda bu kuralı yasal olarak göz ardı edebilir , ancak bu özel durumda bu istisna geçerli değildir.
user694733


30

Her şey sırayla. C, yani ISO / IEC 9899 19 yıldır boole tipine sahip . Bu, bu soruyu ziyaret ederken amatör / akademik / profesyonel bölümlerle birlikte C programlama kariyerinin beklenen süresinden çok daha uzun bir süre . Benimki bunu belki 1-2 yıl geçiyor. Bu, ortalama bir okuyucunun C hakkında hiçbir şey öğrenmediği sırada C'nin aslında boole veri türüne sahip olduğu anlamına gelir .

Veri türü #include <stdbool.h>ve true, falseve için bool. Ya da, ve kullanımını içermez _Bool, 1ve 0bunun yerine.


Bu konuya verilen diğer cevaplarda teşvik edilen çeşitli tehlikeli uygulamalar vardır . Onlara hitap edeceğim:

typedef int bool;
#define true 1
#define false 0

Bu hayır-hayır, çünkü 19 yıl içinde C öğrenen sıradan bir okuyucu bool, bunun gerçek bool veri türüne atıfta bulunmasını ve benzer şekilde davranmasını beklerdi , ama öyle değil! Örneğin

double a = ...;
bool b = a;

C99 ile bool/ _Bool, batanabilir false IFF a sıfır ve oldu trueaksi. C11 6.3.1.2p1

  1. Herhangi bir skaler değer dönüştürüldüğünde _Bool, değer 0 ile karşılaştırılırsa sonuç 0 olur; aksi takdirde sonuç 1 olur. 59)

Dipnotlar

59) NaN'ler 0'a eşit değildir ve bu nedenle 1'e dönüşür.

İle typedefyerinde, doublebir coerced olacağını intçift değeri aralığında değilse - int, davranış tanımlanmamış .

Doğal olarak aynı ise uygulanır trueve falsebir beyan edilmiştir enum.

Ne olduğunu bile daha tehlikeli ilan edilir

typedef enum bool {
    false, true
} bool;

çünkü şimdi 1 ve 0 dışındaki tüm değerler geçersizdir ve böyle bir değerin bu türdeki bir değişkene atanması gerektiğinden , davranış tamamen tanımsız olur .

Bu nedenle IFF bazı açıklanamaz nedenle C99 kullanamaz, boolean değişkenler için kullanmalısınız:

  • tür intve değerler 0ve 1 olduğu gibi ; ve diğer herhangi bir değerden bunlara etki alanı dönüşümlerini dikkatlice çift olumsuzlama ile yapın!!
  • ya eğer ısrar sen 0, falsy ve sıfır olmayan Truish olduğunu hatırlamıyorum az kullanılması en büyük harf onlar C99 kavramları ile karıştırılmamalıdır alamadım böylece: BOOL, TRUEve FALSE!

1
C Standardının hangi bölümü numaralandırılmış türdeki nesnelerin burada açıkça listelenen değerleri tutmasıyla sınırlar? Numaralandırılmış sabit için en büyük değer UCHAR_MAX veya USHRT_MAX değerinden düşükse, bir uygulama numaralandırmadan daha küçük bir türü kullanabilir intveya unsigned intnumaralandırmanın tamsayıdan başka bir şey olarak davranmasına neden olacak hiçbir şey bilmiyorum yazın.
supercat

18
typedef enum {
    false = 0,
    true
} t_bool;

2
2'den MAX_INT'e doğru olarak değerlendirilmelidir
technosaurus

2
@technosaurus Bu yaklaşımı benimsemeniz garanti etmez! false == true!! false sıfırdan farklı bir sayı olabilir. Basit bir çözüm açıkça! False öğesine doğru atamak olacaktır.
Andrew

3
@Andrew Bu doğru değil. !0 = 1C standardına göre ve !a = 0sıfır olmayan herhangi bir değeri için a. Sorun, sıfır olmayan herhangi bir şeyin doğru olarak kabul edilmesidir. Yani ave eğer bher ikisi de "doğru" ise, mutlaka "a == b" söz konusu değildir.
Jeremy West

14

C'nin bir boole türü vardır: bool (en azından son 10 (!) Yıl için)

Dahil stdbool.h ve true / false beklendiği gibi çalışacaktır.


12
Standart olarak 10 yıl, derleyicide 10 yıl değil! MSVC ++ 'ın C derlemesi // yorumlara izin vermekten başka C99'u desteklemez ve bunu yapması pek olası değildir. Ayrıca _Bool C99'da yerleşik bir tür olarak tanımlanırken, bool <stdbool.h> başlığında bir typedef'tir.
Clifford

5
@Clifford Yorumunuzdan 4 yıl sonra ... hiçbir şey değişmedi. MSVC bir C ++ derleyicisidir ve MS'in tüm yeni C özelliklerini (C99 ve C11) desteklemeye gerçekten istekli olmadıklarını söylediğine inanıyorum. Ama MSVC'nin yeni C özelliklerini bir sebep olarak desteklemediğini kabul edemiyorum (özellikle 10 yıl boyunca cevap verdiğinizde ). Programlama dünyasında 10 yıl gerçekten uzun bir zaman. İyi bir derleyici, eğer satıcı desteklemeyi amaçlıyorsa, 10 yıldan daha kısa bir süre içinde bu desteğe sahip olmalıdır.
PP

2
@KingsIndian: Yorumunuzu neden bana yönlendirdiğinizden ve hatta yorum yapma gereğini hissettiğinizden emin değilim. Durumu sadece yazarken olduğu gibi söylüyordum. Bu durumu desteklemiyordum, sadece "cevap" ın her koşulda geçerli olmayacağına dikkat çekiyordum.
Clifford

@Clifford: Kesinlikle, standardın boolgenişleyen bir makro olması gerekir _Bool. Fark önemlidir çünkü #undefbir makro yapabilirsiniz (ve buna izin verilir, en azından geçici bir önlem olarak), ancak untypedeftypedef'i kullanamazsınız . Yine de, ilk yorumunuzun ana itişini değiştirmez.
Jonathan Leffler

2
VS2015 ve üzeri (ve muhtemelen daha önce, bir noktaya kadar) ile bir sorunum yok boolyoluyla <stdbool.h>C derleme altında. Karar verir _Bool.

11

Boole olmayan işlemlerde sıfır olmayan her şey true olarak değerlendirilir, böylece

#define TRUE 1
#define FALSE 0

ve sabitleri kullanın.


10
ancak dikkatli kullanın: gerçek bir sonuç sıfırdan farklı herhangi bir değer olabileceğinden, diğer dillerde eşdeğer olan (t == TRUE) {...} ve (t) 'nin C .
Fortega

1
Haklısın, ama bu bool tipi olan C ++ için de geçerli, değil mi? Hata ayıklama sırasında 5837834939 değerlerine sahip bool değişkenleri gördüm ...
ggambett

1
C ++ 'da if (t == true) testi if (t) testine eşittir, çünkü C ++ bazı dönüşümler yapar (0 olmayan veya boş bir işaretçi değeri her şey true değerine dönüştürülür)
Fortega

6
Bir boolean true değeri hakkında varsaymanız gereken tek şey, sıfır olmadığıdır. Bu nedenle, (b == TRUE) değilse; ikincisi kötü bir uygulamadır (ve anlamsızdır).
Clifford

5

C99 kullanmanıza izin verilirse, diğer cevapları ve bazı açıklamaları tamamlamanız yeterlidir.

+-------+----------------+-------------------------+--------------------+
|  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   |
+-------+----------------+-------------------------+--------------------+

Bazı tercihlerim:

  • _Boolveya bool? Her ikisi de iyi, ancak boolanahtar kelimeden daha iyi görünüyor _Bool.
  • Kabul Edildi değerler boolve _Boolşunlardır: falseya true. Atama 0veya 1yerine falseveya truegeçerli, ancak okumak ve mantık akışını anlamak zordur.

Standarttan bazı bilgiler:

  • _BoolDEĞİL unsigned int, ancak grup işaretsiz tamsayı türlerinin bir parçasıdır . Değerleri tutacak kadar büyük 0veya 1.
  • YAPMAYIN, ancak evet, yeniden tanımlayabilirsiniz bool trueve falseancak iyi bir fikir değildir. Bu yetenek eskimiş kabul edilir ve gelecekte kaldırılacaktır.
  • Veya bir skaler tip (aritmetik tipler ve işaretçi tipleri) atamak , skaler değer buna eşit veya onunla karşılaştırılırsa , aksi takdirde sonuç : atandığında dönüştürülür ._Boolbool0001_Bool x = 9; 91x
  • _Bool1 byte (8 bit), genellikle programcı diğer bitleri kullanmaya denemek için cazip olduğunu, ancak yalnızca verildiği garanti yalnızca bir bit olduğu için tavsiye edilmez değil, tipi gibi veri depolamak için kullanılmasıdır char8 var bit kullanılabilir.

2

O bu:

#define TRUE 1
#define FALSE 0

7
#Define gibi bir şeyle DOĞRU YANLIŞ
Tom

2

Bunun için bir karakter veya başka bir küçük sayı kabı kullanabilirsiniz.

Sözde kod

#define TRUE  1
#define FALSE 0

char bValue = TRUE;

Ayrıca C genellikle bir int, ve int kullanan başka bir kod tarafından hassas uyarı kaybına neden olabilir ..
Thomas Bonini

Alan için el optimizasyonu yapmadığınız sürece, donanımın normal kelime boyutunu (örn. Genellikle bir int) kullanmak her zaman daha iyidir , çünkü bazı mimarilerde bu değişkenler üzerindeki kontrolleri açmak / maskelemek zorunda kalmaktan önemli bir performans artışı elde edersiniz.
Kingsley

2

_Bool kullanabilirsiniz, ancak dönüş değeri bir tamsayı olmalıdır (true için 1, false için 0). Dedi Ancak, ++ dahildir ve C gibi kullanım bool önerilir bu yanıttan gelen daniweb forumda yanı sıra bu cevap bu diğer stackoverflow sorudan,:

_Bool: C99'un boole türü. _Bool'u doğrudan kullanmak yalnızca bool, true veya false için makroları tanımlayan eski kodu koruyorsanız önerilir. Aksi takdirde, bu makrolar başlıkta standartlaştırılır. Bu üstbilgiyi ekleyin ve boole C ++ 'da yaptığınız gibi kullanabilirsiniz.


2

Koşullu ifadeler sıfırdan farklıysa doğru kabul edilir, ancak C standardı mantıksal işleçlerin kendilerinin 0 veya 1 döndürmesini gerektirir.

@Tom: #define DOĞRU! YANLIŞ kötü ve tamamen anlamsız. Başlık dosyası derlenmiş C ++ koduna girerse sorunlara yol açabilir:

void foo(bool flag);

...

int flag = TRUE;
foo(flag);

Bazı derleyiciler int => bool dönüşümü hakkında bir uyarı oluşturur. Bazen insanlar bunu yaparak kaçınırlar:

foo(flag == TRUE);

ifadeyi bir C ++ boole olmaya zorlamak. Ama eğer DOĞRU! YANLIŞ # tanımlıyorsanız, sonuçta:

foo(flag == !0);

bu da uyarıyı yine de tetikleyebilecek bir bool-içi karşılaştırması yapar.


1

C99 kullanıyorsanız, _Booltürü kullanabilirsiniz . Hiçbir #includes gerekli. Nerede olsa Sen, bir tamsayı gibi davranın gerekiyor 1ise trueve 0olduğufalse .

Ardından TRUEve öğelerini tanımlayabilirsiniz FALSE.

_Bool this_is_a_Boolean_var = 1;


//or using it with true and false
#define TRUE 1
#define FALSE 0
_Bool var = TRUE;

Ya da kullanabilirsiniz #include <stdbool.h>ve kullanabilirsiniz bool, trueve falsestandart gibi istiyor.
SS Anne

1

Günümüzde C99 , boole türlerini desteklemektedir, ancak yapmanız gerekir #include <stdbool.h>.

Misal:

#include <stdbool.h>

int main() 
{ 
    bool arr[2] = {true, false}; 

    printf("%d\n", arr[0] && arr[1]);
    printf("%d\n", arr[0] || arr[1]);

    return 0; 
} 

Çıktı:

0
1

0

Ne kullanıyorum:

enum {false, true};
typedef _Bool bool;

_Bool C'de yerleşik bir tiptir. Boole değerleri için tasarlanmıştır.


-2

#defineDirektifi aşağıdaki gibi kullanabilirsiniz :

#define TRUE 1
#define FALSE 0
#define NOT(arg) (arg == TRUE)? FALSE : TRUE
typedef int bool;

Ve aşağıdaki gibi kullanın:

bool isVisible = FALSE;
bool isWorking = TRUE;
isVisible = NOT(isVisible);

ve bunun gibi


5
Makro DEĞİL etrafında parantez korunmalıdır argve bir bütün olarak ifade: #define NOT(arg) (((arg) == TRUE) ? FALSE : TRUE). Bununla birlikte, yanlışlığı test etmek daha iyi olacaktır arg(0 veya 1 yerine 23 olsa bile doğru cevabı verecektir : #define NOT(arg) (((arg) == FALSE) ? TRUE : FALSE)Ancak tüm ifade #define NOT(arg) (!(arg))elbette aynı sonucu veren azaltılabilir
Jonathan Leffler
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.