C standardı, doğruluk değerini açıkça 0 veya 1 olarak mı gösteriyor?


86

Eşit olmayan tüm sayıların C'deki 0gibi görüldüğünü biliyoruz true, böylece yazabiliriz:

Ancak doğru / yanlışın C olarak 1/ olarak tanımlanıp tanımlanmadığını merak ediyordum 0, bu yüzden aşağıdaki kodu denedim:

Mu C standart açıkça gerçeği gerçek değerlerini gibi false belirtmek 1ve 0sırasıyla?


3
Sanırım bu SO Sorusu alakalı
Imran Ali

3
Bu altından çalıştırmayı gccile -std=c89ve aynı sonucu verir.
Kevin Dong

1
@Blackhole, 15'ten 0'a
Arturo Torres Sánchez

6
Neredeyse çift ama SO / SE'den on yıldan fazla bir süre önce: c-faq.com/bool/bool2.html .
dave_thompson_085

1
Yanlış olan sıfır kanon'dur, ancak doğru genellikle "sıfır değil" olarak düşünülür. Ancak programcılar oldukları gibi, çeşitli nedenlerimizden dolayı hepimiz 1'i "sıfır değil" olarak kullandık. Bir doğruya tam olarak 1 olduğu için güvenmemeniz önerilir. Örneğinizde (0 == 0) bir iken, (12 == 12) gibi bir şey de aynı şekilde kolayca 12 değerine sahip olabilir; o da doğru".
Engineer

Yanıtlar:


96

C standardı, sırasıyla trueve falseas 0ve 1sırasıyla doğruluk değerlerini açıkça gösteriyor mu?

C standardı, ve sırasıyla genişleyen makroları trueve falseolarak tanımlar . stdbool.h10

C11-§7.18:

Kalan üç makro #ifönişleme yönergelerinde kullanım için uygundur . Onlar

bu tamsayı sabit genişler 1,

tam sayı sabitine genişleyen 0[...]

Operatörler için ==ve !=standart diyor

C11-§6.5.9 / 3:

==(E eşit) ve !=operatörler düşük önceliğe haricinde ilişkisel operatörlere benzer olan (değil eşit). 108) Operatörlerin her biri, 1belirtilen ilişki doğruysa ve 0yanlışsa sonuç verir. Sonucun türü var int. Herhangi bir işlenen çifti için, ilişkilerden tam olarak biri doğrudur.


20
Soru ile ilgili olduğunu bana öyle geliyor 0 == 0ve 0 != 0vb makro değil değeri.
MM

9
Sanırım yazdığında true"gerçek bir karşılaştırmanın değerini" kastettiğini, makroyu değiltrue
MM

1
@KevinDong; Evet, C99 taslağında benzer paragraf var.
haccks

1
@haccks: "Özdeş" tereddüt etmeden bu konuda söyleyebilirsiniz. Gerektiğinde c99'a atıfta bulunduğum için paragraf bazında bakamayacak kadar tembel olduğum için teklifinizi az önce söyledim. Ve onu sadece ctrl+ f;) ile arayarak
bulabildim

2
@MooingDuck: NaN == NaNyanlış ve NaN != NaNdoğrudur. Bu ifadede bir sorun yok.
kennytm

51

C11'de açıkça belirtilmemiştir. Tüm dil düzeyindeki işlemler 1'i doğru olarak döndürür (ve NaN dahil olmak üzere sıfırdan farklı olanları doğru olarak kabul eder).

  • Eğer endişe yaklaşık Eğer _Boolstandart sadece gerektirdiğinden, daha sonra gerçek 1 olmalı denir tutmak için 0 ve 1 (§6.2.5 / 2).
  • Ayrıca <stdbool.h>makroda truegenişler 1(§7.18 / 3)
  • ==, !=, <, >, <=Ve >=geri 0 veya 1 (§6.5.8 / 6, §6.5.9 / 3).
  • !, &&Ve ||geri 0 veya 1 (§6.5.3.3 / 5/3 §6.5.13, §6.5.14 / 3)
  • defined 0 veya 1'e genişler (§6.10.1 / 1)

Ancak tüm standart kütüphane işlevleri örneğin islowerdoğruluk için "sıfır olmayan" deyin (örn. §7.4.1 / 1, §7.17.5.1 / 3, §7.30.2.1 / 1, §7.30.2.2.1 / 4).


§6.2.5 / 2 : Tür olarak bildirilen bir nesne _Bool, 0 ve 1 değerlerini depolayacak kadar büyüktür.

§6.5.5.3 / 5 : Mantıksal olumsuzlama operatörünün sonucu !, işleneninin değeri 0'a eşit değilse 0'dır, işlenenin değeri 0'a eşitse 1 ...

§6.5.8 / 6 : Operatörlerin her biri <(küçüktür), >(büyüktür), <=(küçüktür veya eşittir) ve >=(büyüktür veya eşittir), belirtilen ilişki doğruysa 1 ve eğer 0 verirse yanlış. 107)…

§6.5.9 / 3 : ==(eşittir) ve !=(eşit değildir) operatörleri, daha düşük öncelikleri haricinde ilişkisel operatörlere benzer. 108 ) Operatörlerin her biri, belirtilen ilişki doğruysa 1, doğru ise 0 verir. yanlış. …

§6.5.13 / 3 : Her &&iki işlenen de eşit olmayan değeri 0 ile karşılaştırırsa, operatör 1 sonucunu verecektir ; …

§6.5.14 / 3 : İşlenenlerinden|| herhangi biri eşit olmayan değeri 0 ile karşılaştırırsa, operatör 1 sonucunu verecektir ; …

§6.10.1 / 1 :… if… şeklinde 1 olarak değerlendirilen - defined identifier- veya - defined ( identifier )- şeklinde tekli operatör ifadeleri içerebilir .

§7.4.1 (Karakter sınıflandırma işlevleri) / 1 : Bu alt bölümdeki işlevler sıfırdan farklı (doğru) döndürür ancak ve ancak…

§7.18 / 3 : Kalan üç makro #ifönişleme direktiflerinde kullanım için uygundur . Bunlar - true- tam sayı sabiti 1'e genişleyen…

§7.17.5.1 / 3 : atomic_is_lock_freeGenel işlev, yalnızca ve ancak nesnenin işlemleri kilitsiz ise sıfırdan farklı (doğru) döndürür. …

§7.30.2.1 (Geniş karakter sınıflandırma işlevleri) / 1 : Bu alt bölümdeki işlevler sıfırdan farklı (doğru) döndürür ancak ve ancak…

§7.30.2.2.1 / 4 : iswctypeİşlev, ancak ve ancak şu durumda sıfırdan farklı (doğru) döndürür…


23

C'de Boole değerleriyle (belirli C bool/_Booltürü yerine doğru / yanlış değerleri kastediyorum) uğraşırken bilmeniz gereken iki standart alan vardır.

İlki , ifadelerin sonucuyla ilgilidir ve çeşitli bölümlerinde bulunabilir C11 6.5 Expressions(örneğin ilişkisel ve eşitlik operatörleri). Sonuç olarak, bir ifade tarafından bir Boolean değeri oluşturulduğunda, o ...

... belirtilen ilişki doğruysa 1, yanlışsa 0 verir. Sonuç, int türüne sahiptir.

Dolayısıyla, evet, Boole üreten herhangi bir ifadenin sonucu doğru için bir veya yanlış için sıfır olacaktır. Eğer ne bulacaksınız Bu maçlar stdbool.hnerede standart makro trueve falseaynı şekilde tanımlanmıştır.

Bununla birlikte, "gönderdiklerinde muhafazakar, kabul ettiklerinde liberal ol" sağlamlık ilkesini izleyerek, tam sayıların Boole bağlamında yorumlanmasının biraz daha rahat olduğunu unutmayın.

Yine, çeşitli bölümlerinden, 6.5aşağıdaki gibi bir dil göreceksiniz:

||İşlenenlerinden ya ise 1 elde edilir operatör 0 eşit karşılaştırın; aksi takdirde 0 verir . Sonuç int türüne sahiptir.

Bundan (ve diğer kısımlarından), sıfırın yanlış kabul edildiği ve diğer herhangi bir değerin doğru olduğu açıktır .


Bir kenara, Boole oluşturma ve yorumlama için hangi değerin kullanıldığını belirten dil de C99 ve C89'da göründüğü için epeydir ortalıkta. K&R bile (ANSI-C ikinci baskı ve ilk baskı) şunu belirtti:

İlişkisel ifadeler ve bunlarla i > jbağlantılı mantıksal ifadeler , doğruysa, yanlışsa değere sahip olacak şekilde tanımlanır .&&||10

Test bölümünde if, while, for, vb "gerçek" sadece "sıfır olmayan" anlamına gelir.

&&Hem işlenen de aksi sıfır, 0 eşitsiz karşılaştırırsanız operatörü ... 1 döndürür.

||Operatör ... Aksi onun operandları ya sıfıra eşit olmayan karşılaştırırsanız 1 ve 0 döndürür.

Makrolar stdbool.hC99'da da görünür, ancak bu başlık dosyası o noktada mevcut olmadığından C89 veya K&R'de görünmez.


2
dikkat ||, ==, !=vb verim int, bir Boole tip
AA

2
Bu soruyu doğru olana oyluyorum. Benim için soru makrolarla değil ilişkisel operatörlerle de ilgilidir.
ckruczek

"Test bölümünde if, while, for, vb 'gerçek dışı sıfır' sadece anlamına gelen ''." Cevabın göze çarpan kısmı bu ve bana göre Dennis Ritchie'nin uzun zaman önce yaptığı talihsiz bir seçim. Genelde dönüş değeri olarak hata kodları döndüren işlevler yazan #define noErr 0ve sıfır olmayan herhangi bir hata kodu bir hatadır. Ve sonra sorun, if ( ready_to_do_something() ){do_something();} işe yaramamanın basitliği ve güzelliğidir . Bu olmak zorunda if ( !not_ready_to_do_something() ){do_something();}, "Bir çok uydurma belgeler vardır, ama sadece tek gerçek." DOĞRU 0 olmalıdır.
robert bristow-johnson

Merak ettiğim için, C kurallarının ilk taslakları "&&" ve "||" davranışını nasıl belirledi? işlenenlerin 0 veya 1 dışında değerlere sahip olduğu durumda? Alıntı yaptığınız metin && ve || ile bağlantılı "mantıksal ifadeler" diyor, ancak ya bu operatörler mantıksal ifadeler dışındaki şeyleri birbirine bağlarsa?
supercat

1
@sdenham, evet. Sahip olduğum en eski K&R kopyasında (ilk baskı, baskı çalıştırma 14, biri o kadar erken ki, dört tipik makinenin, PDP-11, Honeywell-6000, IBM-370 ve Interdata-8 / 32'nin donanım özelliklerinden bahseder), A.7.6/7/10/11(ilişkisel / eşitlik / mantıksal-ve / mantıksal-veya) tümü, sonuç olarak 0 veya 1 verdiğini belirtir. Bunu içerecek şekilde güncellenmiş yanıtı var.
paxdiablo

10

Pek çok farklı şeyi karıştırıyorsunuz: kontrol ifadeleri, operatörler ve boole türleri. Her birinin kendi kuralları vardır.

Kontrol ifadeleri, örneğin ifC11 6.4.8.1 ifadesi gibi çalışır :

Her iki formda da, ifade eşit olmayan değeri 0 ile karşılaştırırsa, ilk ikame yürütülür.

while, forVb aynı kural vardır. Bunun "doğru" veya "yanlış" ile ilgisi yoktur.

Boole sonucunu verdiği varsayılan operatörler için, gerçekte int1 veya 0 değerine sahip bir sonuç veriyorlar. Örneğin eşitlik operatörleri, C11 6.5.9:

Operatörlerin her biri, belirtilen ilişki doğruysa 1, yanlışsa 0 verir

Yukarıdakilerin tümü, 1999 yılına kadar C'nin bir boole türüne sahip olmadığı ve bir tane alsa bile, yukarıdaki kuralların değiştirilmediği içindir. Bu nedenle, deyimlerin ve operatörlerin bir boole türü verdiği (C ++ ve Java gibi) diğer programlama dillerinin çoğundan farklı olarak, sadece intsıfır değerine sahip veya sıfır olmayan bir an verirler . Örneğin, sizeof(1==1)C'de 4, C ++ 'da 1 verir.

C'deki gerçek boole türü adlandırılır _Boolve modern bir derleyici gerektirir. Başlık stdbool.htanımlar makrolar bool, trueve falsegenişletmek, _Bool, 1ve 0(C ++ ile uyumluluk için) olarak bulundu.


Bununla birlikte, kontrol ifadelerini ve işleçleri, bir boole türünü gerçekten gerekliyormuş / vermiş gibi ele almak iyi bir programlama uygulaması olarak kabul edilir. MISRA-C gibi belirli kodlama standartları böyle bir uygulamayı tavsiye eder. Yani:

if(ptr == NULL)yerine if(ptr).

if((data & mask) != 0)yerine if(data & mask).

Bu tarzın amacı, statik analiz araçları yardımıyla tip güvenliğini artırmak ve bu da hataları azaltmaktır. Muhtemelen, bu tarz yalnızca statik çözümleyiciler kullanıyorsanız anlamlıdır. Bazı durumlarda daha okunabilir, kendi kendini belgeleyen koda yol açsa da, örneğin

Güzel, niyet açık, kod kendi kendini belgeliyor.

karşı

Kötü. Bir şey ifade edebilir cve kodu anlamak için türünü aramalıyız . Tamsayı mı, işaretçi mi yoksa karakter mi?


1
sizeof(bool)C ++ 'da uygulamaya özgüdür. Stackoverflow.com/questions/4897844/is-sizeofbool-defined adresine bakın .
David Hammen

@DavidHammen Sizeof (0 == 0) 'ın uygulama tanımlı olması gibi. Bu sadece bir örnek.
Lundin

C'nin Boolean türlerinin kurallarını değiştirdiğini sanıyordum. Diğer uintN türleri (birçok eski derleyicinin "bit" türleri dahil), bir değerin daha düşük N bitlerini depolar ve daha yüksek bitleri yok sayarken, yeni Boolean türleri etkin "veya" tüm bitleri birlikte "yapar.
supercat

1
Olmalı mı if(ptr != NULL)yoksa belki if(!ptr)mi?
Mathieu K.

1
if(c == '\0')Kendini özellikle yeni başlayanların kodlama hatasına borçludur if(c = '\0'), bu yüzden bundan kaçınıyorum. Kabul edildi, if(c)kötü ... örneğin,if(valveIsOpen)
aja

4

Birçok dilde programladım. Dile bağlı olarak doğru 1 veya -1 olarak gördüm. 1'in gerçek olmasının arkasındaki mantık, bir bitin 0 ya da 1 olmasıdır. Gerçek -1 olmasının arkasındaki mantık,! operatör bir kişinin tamamlayıcısıydı. Bir int'teki tüm 1'leri 0'lara ve tüm 0'ları 1'lere değiştirdi. Yani, bir int için,! 0 = -1 ve! (- 1) = 0. Bu beni, bir şeyi == doğru olarak karşılaştırmayacağım, bunun yerine! = Yanlış ile karşılaştıracak kadar tetikledi. Bu şekilde benim programlama tarzım her dilde çalışıyor. Bu yüzden cevabım endişelenmek değil, kodunuz her iki şekilde de doğru çalışacak şekilde programlamaktır.


nasıl olabilir ! tüm 0’ları 1’lere değiştirin ve hala! 5 için 0 üretilsin mi?
codeshot

@codeshot Yapamaz. Ancak dikkat çektiği nokta, tüm dillerin işleneni ele almamasıdır! boole olarak. Bazı muamele! C ~ olarak - yani bitsel bir tamamlayıcıdır. Bu durumda, sonuçta ortaya çıkan değeri belirlemek, ilk etapta değişkenin türünü bilmeyi gerektirir, bu nedenle! (Uint32_t) 5, 4,294,967,290 olacaktır. Ama! 0 hala 4,294,967,295 ve 4,294,967,295 doğrudur.
Pegasus Epsilon

1

Bu cevaba biraz daha yakından bakılması gerekiyor.

C ++ 'daki gerçek tanım, 0 olmayan herhangi bir şeyin doğru olarak değerlendirilmesidir. Bu neden alakalı? C ++ onun hakkında nasıl düşündüğümüzle bir tamsayının ne olduğunu bilmediğinden - bu anlamı yaratıyoruz, sahip olduğu tek şey kabuk ve bunun ne anlama geldiğine dair kurallar. Bitlerin ne olduğunu, tamsayıyı oluşturan bitlerin ne olduğunu bilir.

1 tamsayı olarak bitlerde gevşek bir şekilde temsil edilir, örneğin 8 bitlik işaretli int 0000 0001 olarak gösterilir. Çoğu zaman görsel olarak gördüğümüz biraz yalandır, -1 işaretli yapısı nedeniyle onu temsil etmenin çok daha yaygın bir yoludur. 'tamsayı'. 1 gerçekten doğru anlam ifade edemez, neden? Çünkü bu DEĞİL işlemi 1111 1110'dur. Bu bir boole için gerçekten büyük bir sorun. Bir boolean hakkında konuştuğumuzda, sadece 1 bittir - gerçekten basit, 0 yanlış ve 1 doğrudur. Tüm mantık işlemleri önemsizdir. Bu nedenle '-1', tamsayılar (işaretli) için 'true' olarak belirlenmelidir. 1111 1111 NOT'ed, 0000 0000 olur - mantık geçerli ve biz iyiyiz. İmzalanmamış girişler biraz karmaşıktır ve geçmişte çok daha yaygın olarak kullanılmıştır - burada 1 doğru anlamına gelir çünkü '

Açıklama bu. Burada kabul edilen cevabın yanlış olduğunu söylüyorum - C / C ++ tanımında net bir tanım yok. Bir boolean bir booleandır, bir tamsayıyı bir boole olarak kabul edebilirsiniz, ancak çıktının bir tamsayı olduğu gerçeği, gerçekte yapılan işlemin bitsel olduğunu söylemez.


4
Soru C ile ilgiliydi, C ++ ile değil.
glglgl

0

İfadenizdeki İlişkisel Operatörler yüzünden oldu printf.

Operatör ==ve operatör!=

Yana (0 == 0)doğru çok tutan, bir değer verir1

oysa, (0 != 0)doğru tutmaz, bir değer verir 0.

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.