Menu

C'de Booleanlar: stdbool.h, _Bool ve Doğruluk

C'nin C99'a kadar boolean türü yoktu. Sıfır yanlıştır, geri kalan her şey doğrudur, karşılaştırmalar int üretir - ve stdbool.h bunun üzerine bool, true ve false ekler. Ayrıca bu tasarımın mümkün kıldığı = ile == hatası.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

C, ilk 27 yılını boolean türü olmadan geçirdi. Bu bir gözden kaçırma değil - sonuçlarıyla daha ilk gün tanıştığınız bir tasarım kararı ve doğrudan ondan doğan meşhur bir hata.

Sıfır Yanlıştır, Geri Kalan Her Şey Doğrudur

C'nin koşul kurallarında özel bir doğru/yanlış değeri yoktur. if, while, for, &&, || ve ! hepsi tam olarak tek bir soru sorar: bu değer sıfır mı?

Negatif sayılar doğrudur. Kesirler doğrudur. Boş olmayan bir gösterici doğrudur. Yalnızca sıfır - hangi türde olursa olsun - yanlıştır.

C kodunun, kuralı bilene kadar aşırı kısa görünen deyimlerle dolu olmasının sebebi budur:

if (count)            /* count sıfır değilse */
if (!count)           /* count sıfırsa */
if (p)                /* p NULL değilse */
if (!strcmp(a, b))    /* metinler eşitse - strcmp eşleşmede 0 döndürür */

Sonuncusu insanları yakalar. strcmp, metinler eşleştiğinde 0 döndürür, dolayısıyla "eşit" bir if içinde "değil" diye okunur. if (strcmp(a, b) == 0) yazmak daha anlaşılırdır ve tam olarak aynı şeyi yapar.

Karşılaştırmalar int Üretir

C'de bir karşılaştırma özel bir tür ifade değildir. Değeri 1 ya da 0 olan sıradan bir int'e değerlenir; onu yazdırabilir, saklayabilir ya da onunla aritmetik yapabilirsiniz:

! operatörü de aynı şekilde çalışır: işleneni sıfırsa 1, değilse 0 üretir. Dolayısıyla !!x, herhangi bir değeri tam olarak 0 ya da 1'e normalleştiren klasik bir deyimdir.

bool, true ve false (C99)

C99, _Bool adında gerçek bir boolean türü ve ona okunaklı bir isim veren bir başlık ekledi:

<stdbool.h> küçücüktür: bool'u _Bool, true'yu 1, false'u 0 olarak tanımlar. Başlığın tamamı budur. Ama onu kullanmak niyeti, int flag = 1;'in asla yapamayacağı biçimde görünür kılar.

_Bool'un gerçekten farklı tek bir davranışı vardır: yalnızca 0 ya da 1 saklar. Sıfırdan farklı herhangi bir değer atamak tam olarak 1'e dönüşür:

printf içinde booleanlar için hâlâ bir %b yoktur - onları %d ile yazdırın ya da kendiniz metne dönüştürün:

C23'te bu daha da basitleşti: bool, true ve false gerçek anahtar kelimeler oldu, dolayısıyla include artık gerekli değil. Bugünkü kodun çoğu hâlâ C17'yi hedefliyor, o yüzden #include <stdbool.h>'yi tutun.

Bir Fonksiyondan Boolean Döndürmek

bool'un yerini en açık biçimde hak ettiği yer burasıdır:

bool dönüş tipi, çağırana değerin ne anlama geldiğini söyler. check_file adlı bir fonksiyondan gelen int dönüş tipi bir boolean, bir sayı ya da bir hata kodu olabilir - ve C kütüphane geleneklerinde çoğu zaman üçüncüsüdür, orada 0 başarı demektir. Türü adlandırmak tahmini ortadan kaldırır.

= ile == Hatası

Atama, atanan değeri üreten bir ifade olduğu ve sıfırdan farklı her değer doğru olduğu için bu derlenir:

Aynı anda iki şey ters gitti. Koşul x'e 5 atayarak değerini yok etti ve sonra sıfırdan farklı olan 5'i test etti, dolayısıyla dal çalıştı. Programda varsayılan olarak ne hata ne de uyarı var.

Daha kötüsü, 0 içeren sürüm dalını hiç çalıştırmaz:

if (found = 0) { /* asla çalışmaz - ve found artık 0 */ }

Yararlılık sırasıyla üç savunma:

Uyarılarla derleyin. -Wall bunu yakalar:

warning: suggest parentheses around assignment used as truth value

Sıfır uyarıya ulaşmak buradaki asıl çözümdür ve bedeli tek bir bayraktır.

Sabiti başa yazın. "Yoda koşulu" yazım hatasını bir derleme hatasına dönüştürür:

if (5 == x)   /* doğru */
if (5 = x)    /* hata: lvalue değil - derleyici sizi durdurur */

Bazı ekipler buna bayılır, bazıları okunmaz bulur; her iki tutum da savunulabilir, ama işe yaradığı kesin.

Kastediyorsanız bilinçli olun. Koşul içinde atama, girdi okumak için gerçekten yararlıdır:

int c;
while ((c = getchar()) != EOF) { ... }

c = getchar() çevresindeki fazladan parantezler öncelik için gereklidir ve aynı zamanda atamanın kasıtlı olduğunu işaret eder. Deyim budur - koşul içindeki atamanız buna benzemiyorsa, muhtemelen bir yazım hatasıdır.

Sık Yapılan Boolean Hataları

true ile karşılaştırmak. if (flag == true), stdbool.h ile çalışır, ama flag 42 tutan bir int olduğu anda bozulur, çünkü 42 == 1 yanlıştır. if (flag) yazın.

Zincirleme karşılaştırmalar. if (0 < x < 10) her zaman doğrudur: 0 < x ifadesi 0 ya da 1 üretir ve ikisi de 10'dan küçüktür. if (x > 0 && x < 10) yazın.

Mantıksal yerine bit düzeyi operatörler. & ve |, && ve || değildir. Kısa devre yapmazlar ve bitleri birleştirirler:

Her iki işlenen de "doğru", yine de a & b sonucu 0. && kastedip & kullanmak, yalnızca belirli değerler için yanlış olan bir koşul üretir ki bu, bulunması en zor hata türüdür.

Kayan noktalı sayıları eşitlik için karşılaştırmak. if (0.1 + 0.2 == 0.3) yanlıştır. Bunun yerine bir tolerans ile karşılaştırın - nedeni için bkz. veri tipleri.

Sıkça Sorulan Sorular

C'nin boolean türü var mı?

C99'dan beri var: _Bool yerleşik bir türdür ve <stdbool.h> eklemek size daha okunaklı bool, true ve false yazımlarını verir. C99'dan önce hiç boolean yoktu - programlar yanlış için 0, doğru için 1 kullanarak int ile idare ederdi; bu hâlâ çalışır ve hâlâ yaygındır.

C'de neler doğru sayılır?

Sıfırdan farklı her değer. Bir koşulda 1, -5, 0.01 ve boş olmayan bir gösterici doğrudur; yalnızca 0, 0.0 ve boş gösterici yanlıştır. Ayrı bir boolean kontrolü yoktur - if (x) yalnızca x'in sıfırdan farklı olup olmadığını test eder.

C'de bool nasıl kullanılır?

#include <stdbool.h> ekleyin, ardından bool ready = true; beklediğiniz gibi çalışır. Perde arkasında bool, yalnızca 0 ya da 1 saklayan _Bool'dur - ona sıfırdan farklı herhangi bir değer atamak tam olarak 1 saklar.

C'de = ile == arasındaki fark nedir?

= atar, == karşılaştırır. if (x = 5), x'e 5 atar ve sonra sıfırdan farklı olan 5'i test eder, dolayısıyla dal her zaman çalışır. if (x == 5) ise eşitliği test eder. Birincisi hatasız derlenir; -Wall ile if (5 == x) yazma alışkanlığı bu yüzden vardır.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA