C'de tanımları gördüm
#define TRUE (1==1)
#define FALSE (!TRUE)
Bu gerekli mi? TRUE değerini 1 ve FALSE değerini 0 olarak tanımlamanın avantajı nedir?
C'de tanımları gördüm
#define TRUE (1==1)
#define FALSE (!TRUE)
Bu gerekli mi? TRUE değerini 1 ve FALSE değerini 0 olarak tanımlamanın avantajı nedir?
Yanıtlar:
Bu yaklaşım , derleyici destekliyorsa gerçek booleantürü kullanır (ve çözümlemesi trueve için false). (özellikle C ++)
Ancak, C ++ (aracılığıyla kullanımda olup olmadığını kontrol etmek daha iyi olurdu __cplusplusmakro) ve aslında kullanmak trueve false.
Bir Cı derleyici, bu eşdeğerdir 0ve 1.
(parantezlerin kaldırılmasının işlem sırası nedeniyle kesileceğini unutmayın)
1==1bir int. (bkz. stackoverflow.com/questions/7687403/… .)
booleantürü ile?
trueveya false.
#define TRUE trueve #define FALSE falsene zaman __cplusplustanımlanır.
Cevap taşınabilirliktir. Sayısal değerleri önemlidir TRUEve FALSEönemli değildir. Ne olduğunu önemlidir gibi bir deyimi o if (1 < 2)kadar değerlendirir if (TRUE)ve benzeri bir açıklamada if (1 > 2)için değerlendirir if (FALSE).
C olarak kabul (1 < 2)edilir 1ve (1 > 2)değerlendirilir 0, diğerlerinin söylediği gibi, derleyici açısından pratik bir fark yoktur. Ancak derleyicinin kendi kurallarına göre tanımlamasına TRUEve FALSEkendi kurallarına göre, anlamlarını programcılara açık hale getiriyorsunuz ve programınızdaki ve diğer kütüphanelerinizde tutarlılığı garanti ediyorsunuz (diğer kütüphanenin C standartlarına uyduğu varsayılırsa ... şaşıracaksınız).
Bazı Geçmişi
Bazı BASICler tanımlandığı FALSEşekilde 0ve TRUEolduğu gibi -1. Birçok modern dil gibi , sıfır olmayan herhangi bir değeri olarak yorumladılarTRUE , ancak doğru olan boole ifadelerini değerlendirdiler-1 . Onların NOTo bu şekilde yapmaya verimli olduğu için operasyon, 1 ekleme ve işareti saygısız tarafından hayata geçirildi. Böylece 'NOT x' oldu -(x+1). Bunun bir yan etkisi, benzeri bir değerin 5değerlendirildiği TRUE, ancak NOT 5değerlendirildiği -6, ki bu da TRUE! Bu tür bir hata bulmak eğlenceli değil.
İyi Uygulamalar
Verilen fiilen sıfır olarak yorumlanır olduğunu kurallarını FALSEve herhangi olarak sıfır olmayan bir değer yorumlanır TRUEsen gerektiğini boole görünümlü ifadeleri karşılaştırmak asla TRUEyaFALSE . Örnekler:
if (thisValue == FALSE) // Don't do this!
if (thatValue == TRUE) // Or this!
if (otherValue != TRUE) // Whatever you do, don't do this!
Neden? Çünkü birçok programcı ints'yi tedavi etme kısayolunu kullanır bool. Aynı değiller, ancak derleyiciler genellikle buna izin verir. Yani, örneğin, yazmak tamamen yasal
if (strcmp(yourString, myString) == TRUE) // Wrong!!!
Bu meşru görünüyor ve derleyici bunu mutlu bir şekilde kabul edecek, ancak muhtemelen istediğinizi yapmaz. Yani en yüzünden dönüş değeri strcmp()DİR
0 ise yourString == myString
<0 ise yourString < myString
> 0 iseyourString > myString
Yani yukarıdaki çizgi TRUEsadece ne zaman geri döner yourString > myString.
Bunu yapmanın doğru yolu ya
// Valid, but still treats int as bool.
if (strcmp(yourString, myString))
veya
// Better: lingustically clear, compiler will optimize.
if (strcmp(yourString, myString) != 0)
Benzer şekilde:
if (someBoolValue == FALSE) // Redundant.
if (!someBoolValue) // Better.
return (x > 0) ? TRUE : FALSE; // You're fired.
return (x > 0); // Simpler, clearer, correct.
if (ptr == NULL) // Perfect: compares pointers.
if (!ptr) // Sleazy, but short and valid.
if (ptr == FALSE) // Whatisthisidonteven.
Genellikle bu "kötü örneklerin" bazılarını üretim kodunda bulacaksınız ve birçok deneyimli programcı onlar tarafından yemin ediyor: çalışıyorlar, bazıları (bilgiçlik?) Doğru alternatiflerinden daha kısadır ve deyimler neredeyse evrensel olarak tanınır. Ancak şunu düşünün: "doğru" sürümler daha az verimli değildir, taşınabilir olmaları garanti edilir, en katı linterleri bile geçer ve hatta yeni programcılar bile bunları anlar.
Buna değmez mi?
(1==1)daha taşınabilir değil 1. Derleyicinin kendi kuralları, eşitlik ve ilişkisel işleçlerin anlambilimi konusunda açık ve net olan C dilinin kurallarıdır. Bir derleyicinin bu şeyleri yanlış yaptığını hiç görmedim.
strcmp0'dan küçük, eşit veya 0'dan büyük olduğu bilinmektedir. -1, 0 veya 1 olduğu garanti edilmez ve wild'da uygulama hızını kazanmak için bu değerleri döndürmeyen platformlar vardır. Eğer strcmp(a, b) == TRUEöyleyse, a > bancak ters ima tutunmayabilir.
(1==1)ve 1her ikisi de int1 değerine sahip sabit tip ifadelerdir. Anlamsal olarak aynıdırlar. Sanırım bunu bilmeyen okuyuculara hitap eden bir kod yazabilirsiniz, ama nerede bitiyor?
(1 == 1)Hüner tanımlamak için yararlıdır TRUEC ++ şeffaf bir şekilde, henüz C daha iyi yazarak sağlar. "Temiz C" (C veya C ++ olarak derlenen) bir lehçede yazıyorsanız veya C veya C ++ programcıları tarafından kullanılabilecek API başlık dosyaları yazıyorsanız, aynı kod C veya C ++ olarak yorumlanabilir.
Cı çeviri birimleri olarak, 1 == 1tam olarak aynı anlamlara sahiptir 1; ile 1 == 0aynı anlama sahiptir 0. Ancak, C ++ çeviri birimlerinde 1 == 1türü vardır bool. Yani TRUEbu şekilde tanımlanan makro C ++ 'a daha iyi entegre olur.
Nasıl daha iyi entegre edileceğinin bir örneği, örneğin işlev fooiçin intve için aşırı yük varsa bool, o foo(TRUE)zaman boolaşırı yükü seçecektir . Eğer TRUEsadece olarak tanımlanır 1, o zaman C ++ içinde güzel çalışmayacaktır. aşırı yük foo(TRUE)isteyecek int.
Tabii ki, C99 tanıtıldı bool, trueve falsebu başlık dosyalarında kullanılabilen C99 ile ve C ile çalışmak olduğunu
Ancak:
TRUEile FALSEolduğu gibi (0==0)ve (1==0)C99 eskidir.Eğer bir karma C ve C ++ projede çalışıyoruz ve C99 istemiyorsanız, alt durum tanımlamak true, falseve boolbunun yerine.
#ifndef __cplusplus
typedef int bool;
#define true (0==0)
#define false (!true)
#endif
Bununla birlikte, 0==0hile, bazı programcılar tarafından hiçbir zaman C ++ ile birlikte çalışması amaçlanmayan kodda bile kullanıldı (?). Bu hiçbir şey satın almaz ve programcının C'de boolelerin nasıl çalıştığını yanlış anladığını gösterir.
C ++ açıklaması net değilse, bir test programı aşağıdadır:
#include <cstdio>
void foo(bool x)
{
std::puts("bool");
}
void foo(int x)
{
std::puts("int");
}
int main()
{
foo(1 == 1);
foo(1);
return 0;
}
Çıktı:
bool
int
Aşırı C ve C ++ programlama ile ilgili aşırı yüklenmiş C ++ fonksiyonlarının yorumlarından gelen soruya gelince. Bunlar sadece bir tip farkı göstermektedir. C ++ olarak derlendiğinde bir truesabitin olmasını istemenin geçerli bir nedeni booltemiz teşhis içindir. En yüksek uyarı düzeylerinde, bir C ++ derleyicisi boolparametre olarak bir tamsayıyı iletirsek, dönüşüm konusunda bizi uyarabilir . Temiz C'de yazmanın bir nedeni sadece kodumuzun daha taşınabilir olması değildir (çünkü sadece C derleyicileri değil, C ++ derleyicileri tarafından da anlaşılır), ancak C ++ derleyicilerinin tanılama görüşlerinden de yararlanabiliriz.
TRUEC ++ altında farklılık göstereceği açık değildir .
#ifdef __cplusplus, niyetinizi çok daha açık bir şekilde ifade etmek için kullanabilirsiniz .
boolve intörtük birbirlerine dönüştürülebilir (ve de çünkü çok önemli değil pratikte do C aslında "aynı" , tırnak dikkat olsa da) ve ikisi arasında gerçekten saptamanız gereken birçok durum yok . "fazla değil" muhtemelen çok ağırdı, "şablonlar ve aşırı yükleme kullanan kodlara kıyasla çok daha az" belki daha iyi olurdu.
#define TRUE (1==1)
#define FALSE (!TRUE)
eşittir
#define TRUE 1
#define FALSE 0
C cinsinden
İlişkisel işleçlerin sonucu 0veya 1. 1==1için değerlendirilmesi 1ve değerlendirilmesi için !(1==1)garanti edilir 0.
İlk formu kullanmak için kesinlikle hiçbir neden yoktur. Bununla birlikte, birinci formun hemen hemen tüm derleyicilerde olduğu gibi, sabit bir ifadenin çalışma zamanında değil, derleme zamanında değerlendirildiğini unutmayın. Bu kurala göre izin verilir:
(C99, 6.6p2) "Sabit bir ifade, çalışma sırasında değil çeviri sırasında değerlendirilebilir ve buna göre, bir sabitin olabileceği herhangi bir yerde kullanılabilir."
PC-Lint, için hazır bilgi TRUEve FALSEmakro kullanmazsanız bir ileti (506, sabit değer boole) bile gönderir :
C için,
TRUEolarak tanımlanmalıdır1. Bununla birlikte, diğer diller 1 dışındaki miktarları kullanır, bu nedenle bazı programcılar!0bunu güvenli oynadığını düşünür.
Ayrıca C99'da, stdbool.hboolean makroları trueve false doğrudan değişmez değerleri tanımları :
#define true 1
#define false 0
1==11
if(foo == true), sadece kötü uygulamadan düz arabayı alacak olan formun kodu için önemlidir .
(x == TRUE), bundan farklı bir gerçek değerine sahip olabilir x.
C ++ (daha önce de belirtilmiş) dışında, bir diğer avantaj da statik analiz araçlarıdır. Derleyici herhangi bir verimsizliği ortadan kaldıracaktır, ancak statik bir analizör karşılaştırma sonuçlarını ve diğer tamsayı tiplerini ayırt etmek için kendi soyut tiplerini kullanabilir, bu nedenle dolaylı olarak TRUE'nun bir karşılaştırmanın sonucu olması gerektiğini ve uyumlu olduğu varsayılmaması gerektiğini bilir. bir tamsayı ile.
Açıkçası C uyumlularsa olduğunu söylüyor, ancak yardım vurgulamak hatalar için bu özellik kasıtlı kullanımını yasaklayan tercih edebilir - örneğin, birileri karıştırmayın olabilir nerede &ve &&ya onların operatör öncelik bungled ettik.
if (boolean_var == TRUE) genişleme yoluyla aptalca kod yakalayabilir . if (boolean_var == (1 == 1))(1 == 1)if (<*> == <boolean_expr>)
Pratik fark yok. 0olarak değerlendirilir falseve 1olarak değerlendirilir true. Bir kullanmak gerçeği boolean ifadesini ( 1 == 1) ya da 1tanımlamak için, trueherhangi bir fark yaratmaz. İkisi de değerlendirilir int.
Uyarı C standart kütüphanesi Boolean tanımlamak için özel bir başlık sağladığını: stdbool.h.
trueolarak değerlendirilir 1ve falseolarak değerlendirilir 0. C yerli boole türlerini bilmiyor, sadece ints.
intdeğer içeren sonuçlar verir . C (gerçek boolean türü var bir makro ile, tanımlanmış , ama bu sadece yoktu, C99 ile eklendi değil yeni türünü kullanmak için operatörlerin semantiğini değiştirin.01_Boolbool<stdbool.h>
_Boolve <stdbool.h>vardır #define bool _Bool.
1 == 1olarak değerlendirilme konusunda haklısınız int. Düzenlenen.
DOĞRU'nun eşit olduğu kesin değeri bilmiyoruz ve derleyicilerin kendi tanımları olabilir. Privode yaptığınız şey derleyicinin dahili tanımını kullanmaktır. İyi programlama alışkanlıklarınız varsa bu her zaman gerekli değildir, ancak bazı kötü kodlama stilleriyle ilgili sorunları önleyebilir, örneğin:
if ((a> b) == DOĞRU)
TRUE değerini manüel olarak 1 olarak tanımlarsanız bu bir felaket olabilirken, TRUE iç değeri başka bir değerdir.
>operatör daima true için 1, false için 0 verir. Herhangi bir C derleyicisinin bunu yanlış anlama olasılığı yoktur. Eşitlik karşılaştırmaları TRUEve FALSEzayıf üslup; yukarıdakiler daha net olarak yazılmıştır if (a > b). Ancak farklı C derleyicilerinin gerçeği ve yanlışları farklı şekilde ele alabileceği fikri yanlıştır.
Tipik olarak C Programlama Dili'nde 1, true olarak ve 0, false olarak tanımlanır. Bu nedenle aşağıdakileri neden sıklıkla görüyorsunuz:
#define TRUE 1
#define FALSE 0
Ancak, koşullu bir ifadede 0'a eşit olmayan herhangi bir sayı doğru olarak değerlendirilir. Bu nedenle aşağıdakileri kullanarak:
#define TRUE (1==1)
#define FALSE (!TRUE)
Yanlış olanı yanlış olana eşit yaparak onu güvenli bir şekilde oynamaya çalıştığınızı açıkça gösterebilirsiniz.
#define TRUE (’/’/’/’):;#define FALSE (’-’-’-’)( coding-guidelines.com/cbook/cbook1_1.pdf sayfa 871 adresinden alınmıştır )