# 1 के बजाय C बूलियन मैक्रो में #define TRUE (1 == 1) क्यों?


160

मैंने सी में परिभाषाएँ देखी हैं

#define TRUE (1==1)
#define FALSE (!TRUE)

क्या यह आवश्यक है? केवल TRUE को 1 के रूप में परिभाषित करने और 0 के रूप में FALSE पर क्या लाभ है?


35
और अधिक #define TRUE (’/’/’/’):; #define FALSE (’-’-’-’)( कोडिंग-guidelines.com/cbook/cbook1_1.pdf पृष्ठ 871 से लिया गया है )
osgx

2
नहीं, यह अव्यक्त ^ Wunderinformed, वास्तव में व्यामोह है। C में, 1 और 0 सभी परिस्थितियों में समान होते हैं।
जेन्स

@osgx इसका क्या मतलब है?
मर्गलूम

जवाबों:


155

यदि संकलक इसका समर्थन करता है तो यह दृष्टिकोण वास्तविक booleanप्रकार (और संकल्प trueऔर false) का उपयोग करेगा। (विशेष रूप से, C ++)

हालांकि, यह जांचना बेहतर होगा कि क्या C ++ उपयोग में है ( __cplusplusमैक्रो के माध्यम से ) और वास्तव में उपयोग करें trueऔर false

एक सी कंपाइलर में, यह 0और के बराबर है 1
(ध्यान दें कि कोष्ठक हटाने से संचालन के क्रम के कारण टूट जाएगा)


7
यह गलत है, यहाँ बूल का उपयोग नहीं किया जाता है। का परिणाम ए 1==1है int। (देखें stackoverflow.com/questions/7687403/… ।)
Mat

4
@ मेत: यहां तक ​​कि सी ++ में, booleanप्रकार के साथ ?
SLAKs

9
प्रश्न C को टैग किया गया है, लेकिन वास्तव में C ++ में रिलेशनल ऑपरेटर वापस आते हैं trueया false
Mat

5
@ मट: मैं अनुमान लगा रहा हूं कि इस तरह का कोड सी हेडर में सी ++ के साथ अच्छा खेलने के लिए लिखा गया है
SLaks

20
@SLaks अगर यह C ++ के साथ अच्छा खेलना चाहता था, तो यह #define TRUE trueऔर #define FALSE falseजब भी __cplusplusपरिभाषित किया जाएगा।
निकोस सी।

137

उत्तर पोर्टेबिलिटी है। के संख्यात्मक मान TRUEऔर FALSEमहत्वपूर्ण नहीं हैं। क्या है महत्वपूर्ण है की तरह एक बयान है कि if (1 < 2)करने के लिए मूल्यांकन करता है if (TRUE)और इस तरह के एक बयान if (1 > 2)करने के लिए मूल्यांकन करता है if (FALSE)

सी में दी गई, का (1 < 2)मूल्यांकन करता है 1और (1 > 2)मूल्यांकन करता है 0, इसलिए जैसा कि दूसरों ने कहा है, जहां तक ​​संकलक का संबंध है, कोई व्यावहारिक अंतर नहीं है। लेकिन संकलक को परिभाषित करने TRUEऔर FALSEअपने स्वयं के नियमों के अनुसार, आप प्रोग्रामर्स को उनके अर्थ स्पष्ट कर रहे हैं, और आप अपने कार्यक्रम और किसी भी अन्य पुस्तकालय में स्थिरता की गारंटी दे रहे हैं (अन्य पुस्तकालय मानकर सी मानकों का पालन करते हैं ... आप चौंकना)।


कुछ इतिहास
कुछ मूल बातें परिभाषित FALSEके रूप में 0और TRUEके रूप में -1। कई आधुनिक भाषाओं की तरह, उन्होंने किसी भी गैर-शून्य मान की व्याख्या कीTRUE , लेकिन उन्होंने बूलियन अभिव्यक्तियों का मूल्यांकन किया जो कि सच थे -1। उनके NOTऑपरेशन को 1 जोड़कर और संकेत को फ़्लिप करके लागू किया गया था, क्योंकि यह इस तरह से करना कुशल था। तो 'नॉट एक्स' बन गया -(x+1)। इसका एक दुष्परिणाम यह है कि जैसे कोई मूल्य का 5मूल्यांकन करता है TRUE, बल्कि उसका NOT 5मूल्यांकन करता है -6, जो है भी TRUE! इस तरह की बग ढूंढना मजेदार नहीं है।

उत्तम आचरण
को देखते हुए वास्तविक नियम है कि शून्य के रूप में व्याख्या की है FALSEऔर किसी भी रूप में गैर-शून्य मान व्याख्या की है TRUE, तो आप चाहिए करने के लिए बूलियन दिखने भाव की तुलना कभी नहीं TRUEयाFALSE । उदाहरण:

if (thisValue == FALSE)  // Don't do this!
if (thatValue == TRUE)   // Or this!
if (otherValue != TRUE)  // Whatever you do, don't do this!

क्यों? क्योंकि कई प्रोग्रामर intएस के रूप में व्यवहार करने के शॉर्टकट का उपयोग करते हैं bool। वे समान नहीं हैं, लेकिन कंपाइलर आमतौर पर इसकी अनुमति देते हैं। इसलिए, उदाहरण के लिए, यह लिखना पूरी तरह से कानूनी है

if (strcmp(yourString, myString) == TRUE)  // Wrong!!!

यह वैध लगता है , और संकलक इसे खुशी से स्वीकार करेगा, लेकिन यह संभवतः वह नहीं करता है जो आप चाहते हैं। इसलिए कि वापसी का मूल्य strcmp()है

      ० अगर yourString == myString
    <० अगर yourString < myString
    > ० अगरyourString > myString

तो ऊपर की लाइन TRUEतभी लौटती है जब yourString > myString

ऐसा करने का सही तरीका या तो है

// Valid, but still treats int as bool.
if (strcmp(yourString, myString))

या

// Better: lingustically clear, compiler will optimize.
if (strcmp(yourString, myString) != 0)

इसी तरह:

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.

आपको अक्सर उत्पादन कोड में इन "खराब उदाहरणों" में से कुछ मिलेंगे, और कई अनुभवी प्रोग्रामर उनके द्वारा कसम खाते हैं: वे काम करते हैं, कुछ उनके (पेडेंटली?) सही विकल्पों की तुलना में कम हैं, और मुहावरों को लगभग सार्वभौमिक मान्यता प्राप्त है। लेकिन विचार करें: "सही" संस्करण कोई कम कुशल नहीं हैं, वे पोर्टेबल होने की गारंटी देते हैं, वे सख्त लिंटर भी पास करेंगे, और यहां तक ​​कि नए प्रोग्रामर भी उन्हें समझेंगे।

क्या इसके लायक नहीं है?


6
(1==1)से अधिक नहीं पोर्टेबल है 1। संकलक के अपने नियम सी भाषा के हैं, जो समानता और संबंधपरक ऑपरेटरों के शब्दार्थ के बारे में स्पष्ट और स्पष्ट है। मैंने कभी नहीं देखा कि एक कंपाइलर को यह सामान गलत मिले।
कीथ थॉम्पसन

1
वास्तव में इसके द्वारा लौटाए गए मान strcmpको तब कम, बराबर या उससे अधिक जाना जाता है। 0. यह -1, 0 या 1 होने की गारंटी नहीं है और जंगल में ऐसे प्लेटफार्म हैं जो कार्यान्वयन की गति हासिल करने के लिए उन मूल्यों को वापस नहीं करते हैं। तो अगर strcmp(a, b) == TRUEतो a > bलेकिन रिवर्स निहितार्थ पकड़ नहीं सकता है।
मैकीज पाइचोटका

2
@KeithThompson - शायद "पोर्टेबिलिटी" गलत शब्द था। लेकिन तथ्य यह है कि (1 == 1) एक बूलियन मूल्य है; 1 नहीं है।
एडम लिस

2
@AdamLiss: C में, (1==1)और मान के साथ 1दोनों प्रकार के निरंतर भाव intहैं। वे शब्दार्थ समान हैं। मुझे लगता है कि आप उस कोड को लिख सकते हैं जो पाठकों को पूरा करता है जो यह नहीं जानते, लेकिन यह कहां समाप्त होता है?
कीथ थॉम्पसन

2
बिट स्तर पर 'नहीं' 5, वास्तव में, -6 है।
विलीविराज

51

यह (1 == 1)ट्रिक TRUEC के पारदर्शी होने के तरीके के लिए उपयोगी है, फिर भी C ++ में बेहतर टाइपिंग प्रदान करती है। यदि आप "क्लीन सी" (जो या तो C या C ++ के रूप में संकलित हैं) या यदि आप एपीआई हेडर फाइल लिख रहे हैं जिसे C या C ++ प्रोग्रामर द्वारा उपयोग किया जा सकता है, तो उसी कोड को C या C ++ के रूप में व्याख्या किया जा सकता है।

C अनुवाद इकाइयों में, 1 == 1इसका ठीक वही अर्थ है जो 1; और 1 == 0जैसा अर्थ है वैसा ही है 0। हालाँकि, C ++ अनुवाद इकाइयों में, 1 == 1प्रकार है bool। तो TRUEमैक्रो ने परिभाषित किया कि जिस तरह से सी ++ में बेहतर एकीकृत करता है।

यह कैसे बेहतर एकीकृत करता है इसका एक उदाहरण यह है कि उदाहरण के लिए यदि फ़ंक्शन के fooलिए intऔर boolउसके बाद अधिभार है , तो अधिभार का foo(TRUE)चयन करेगा bool। तो TRUEबस के रूप में परिभाषित किया गया है 1, तो यह सी ++ में अच्छी तरह से काम नहीं करेगा। ओवरलोड foo(TRUE)चाहते हैं int

बेशक, C99 पेश किया bool, trueऔर falseऔर इन हेडर फाइल में इस्तेमाल किया जा सकता है कि C99 के साथ और सी के साथ काम

तथापि:

  • को परिभाषित करने के लिए इस अभ्यास TRUEऔर FALSEके रूप में (0==0)और (1==0)पहले का C99।
  • C99 से दूर रहने और C90 के साथ काम करने के लिए अभी भी अच्छे कारण हैं।

यदि आप मिश्रित C ​​और C ++ प्रोजेक्ट में काम कर रहे हैं, और C99 नहीं चाहते हैं, तो निचले-मामले को परिभाषित करें true, falseऔर boolइसके बजाय।

#ifndef __cplusplus
typedef int bool;
#define true (0==0)
#define false (!true)
#endif

कहा जा रहा है, 0==0चाल थी (है?) कुछ प्रोग्रामर द्वारा कोड में भी इस्तेमाल किया गया था जो किसी भी तरह से सी ++ के साथ हस्तक्षेप करने का कभी नहीं था। यह कुछ भी नहीं खरीदता है और सुझाव देता है कि प्रोग्रामर को गलतफहमी है कि सी में बुलियन कैसे काम करते हैं।


मामले में C ++ स्पष्टीकरण स्पष्ट नहीं था, यहाँ एक परीक्षण कार्यक्रम है:

#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;
}

उत्पादन:

bool
int

मिश्रित C ​​और C ++ प्रोग्रामिंग के लिए प्रासंगिक ओवरलोड सी ++ फ़ंक्शन की टिप्पणियों से सवाल के रूप में। ये सिर्फ एक प्रकार का अंतर बताते हैं। स्वच्छ निदान के लिए C ++ के रूप में संकलित होने के लिए एक trueनिरंतर होने की इच्छा के लिए एक वैध कारण bool। यदि हम एक boolपैरामीटर के रूप में पूर्णांक पास करते हैं, तो इसके उच्चतम चेतावनी स्तरों पर, C ++ कंपाइलर हमें रूपांतरण के बारे में चेतावनी दे सकता है । क्लीन सी में लिखने का एक कारण यह भी नहीं है कि हमारा कोड अधिक पोर्टेबल है (क्योंकि यह C ++ कंपाइलर द्वारा समझा जाता है, न केवल C कंपाइलर), लेकिन हम C ++ कंपाइलर के नैदानिक ​​राय से लाभ उठा सकते हैं।


3
बहुत बढ़िया, और हामी भर दी, जवाब। यह बिल्कुल स्पष्ट नहीं है कि दो परिभाषाएँ TRUEC ++ के अंतर्गत अलग-अलग होंगी।
user4815162342

4
कोड के लिए अतिभारित कार्य कैसे प्रासंगिक हैं जो C और C ++ दोनों के रूप में संकलित हैं?
कीथ थॉम्पसन

@KeithThompson यह ओवरलोडिंग के बारे में नहीं है, बल्कि सामान्य रूप से उचित टाइपिंग है, जब यह खेल में आता है तो ओवरलोडिंग केवल सबसे व्यावहारिक उदाहरण है। ओवरलोड, टेम्प्लेट और "सी-कम्पैटिबिलिटी" के लिए हटाए गए "जटिल" सामान के बिना बेशक सी ++ कोड वास्तव में सभी प्रकार के बारे में बहुत परवाह नहीं करता है, लेकिन इसका मतलब यह नहीं है कि किसी दिए गए भाषा में वैचारिक प्रकार की सीमाओं को उखाड़ फेंकना चाहिए। ।
ईसाई राऊ

1
@ChristianRau: आपका क्या मतलब है "वास्तव में बहुत प्रकार के बारे में परवाह नहीं करता है"? प्रकार सी भाषा के लिए केंद्रीय हैं; C प्रोग्राम में हर एक्सप्रेशन, वैल्यू और ऑब्जेक्ट अच्छी तरह से परिभाषित है। यदि आप C और C ++ में कुछ अलग परिभाषित करना चाहते हैं ( दुर्लभ मामलों में जहां आपको वास्तव में कोड लिखने की आवश्यकता है जो C और C ++ दोनों के रूप में संकलित होती है), तो आप #ifdef __cplusplusअपने इरादे को अधिक स्पष्ट रूप से व्यक्त करने के लिए उपयोग कर सकते हैं ।
कीथ थॉम्पसन

@KeithThompson हां मुझे पता है कि महत्वपूर्ण प्रकार कैसे होते हैं। यह सिर्फ इतना ही है कि ओवरलोडिंग और टेम्प्लेट जैसे सभी प्रकार के जागरूक सामानों के बिना, बीच के भेदभाव जैसी चीजें boolऔर intव्यवहार में ज्यादा मायने नहीं रखती हैं, क्योंकि वे एक-दूसरे के लिए अनुमानित रूप से परिवर्तनीय हैं (और सी में वास्तव में "समान" , उद्धरण नोट करें , हालांकि) और ऐसी कई स्थितियाँ नहीं हैं जिनमें आपको वास्तव में दोनों के बीच की अवहेलना करने की आवश्यकता है । "बहुत ज्यादा नहीं" शायद बहुत भारी था, "खाकों और ओवरलोडिंग का उपयोग करने वाले कोड की तुलना में बहुत कम" शायद बेहतर होता।
ईसाई रौ

18
#define TRUE (1==1)
#define FALSE (!TRUE)

के बराबर है

#define TRUE  1
#define FALSE 0

सी। में।

संबंधित ऑपरेटरों का परिणाम है 0या 11==1का मूल्यांकन करने की गारंटी है 1और !(1==1)इसका मूल्यांकन करने की गारंटी है 0

पहले रूप का उपयोग करने का कोई कारण नहीं है। ध्यान दें कि पहला रूप हालांकि कम कुशल नहीं है क्योंकि लगभग सभी संकलक पर एक स्थिर अभिव्यक्ति का मूल्यांकन रन-टाइम के बजाय संकलन समय पर किया जाता है। यह इस नियम के अनुसार अनुमत है:

(C99, 6.6p2) "रनटाइम के बजाय अनुवाद के दौरान एक निरंतर अभिव्यक्ति का मूल्यांकन किया जा सकता है, और तदनुसार किसी भी स्थान पर उपयोग किया जा सकता है जो एक स्थिर हो सकता है।"

यदि आप मैक्रो TRUEऔर FALSEमैक्रोज़ के लिए शाब्दिक उपयोग नहीं करते हैं, तो पीसी-लिंट भी एक संदेश (506, निरंतर मूल्य बूलियन) जारी करेगा।

सी के लिए, TRUEको परिभाषित किया जाना चाहिए 1। हालांकि, अन्य भाषाएं 1 के अलावा अन्य मात्राओं का उपयोग करती हैं इसलिए कुछ प्रोग्रामर को लगता है कि !0यह सुरक्षित है।

इसके अलावा C99 में, stdbool.hबूलियन मैक्रोज़ की परिभाषा trueऔर false सीधे शाब्दिक उपयोग के लिए:

#define true   1
#define false  0

1
मुझे संदेह है, TRUE को हर उपयोग पर 1 == 1 से बदल दिया जाता है, जबकि सिर्फ 1 का उपयोग करने पर 1 को बदल दिया जाएगा, क्या पहली विधि अतिरिक्त तुलना ओवरहेड नहीं है ... या इसे अनुकूलित कंपाइलर बनाया गया है?
गुलाबीपानी

4
@pinkpanther निरंतर अभिव्यक्तियों का आमतौर पर संकलन समय पर मूल्यांकन किया जाता है और इसलिए किसी भी ओवरहेड को प्रेरित नहीं करते हैं।
ahउउ

2
1==1का मूल्यांकन करने की गारंटी है1
ouah

3
@NikosC। यह एक अच्छा सवाल है। यह फॉर्म के कोड के लिए मायने रखता है if(foo == true), जो केवल खराब अभ्यास से फ्लैट-आउट बग्गी तक जाएगा।
djechlin

1
+1 में खतरों को इंगित करने के लिए की (x == TRUE)तुलना में एक अलग सत्य मूल्य हो सकता है x
जोशुआ टेलर

12

सी ++ (पहले से उल्लेख किया गया) के अलावा, एक और लाभ स्थिर विश्लेषण उपकरण के लिए है। संकलक किसी भी अक्षमता के साथ दूर करेगा, लेकिन एक स्थिर विश्लेषक तुलनात्मक परिणामों और अन्य पूर्णांक प्रकारों के बीच अंतर करने के लिए अपने स्वयं के सार प्रकारों का उपयोग कर सकता है, इसलिए यह स्पष्ट रूप से जानता है कि TRUE एक तुलना का परिणाम होना चाहिए और इसे संगत नहीं माना जाना चाहिए। एक पूर्णांक के साथ।

स्पष्ट रूप से सी का कहना है कि वे संगत हैं, लेकिन आप बग को उजागर करने में मदद करने के लिए उस सुविधा के जानबूझकर उपयोग को प्रतिबंधित करने का विकल्प चुन सकते हैं - उदाहरण के लिए, जहां किसी ने भ्रमित किया हो सकता है &और &&, या उन्होंने अपने ऑपरेटर की पूर्ववर्ती स्थिति को भुनाया है।


1
यह एक अच्छा बिंदु है, और हो सकता है कि इनमें से कुछ उपकरण if (boolean_var == TRUE) विस्तार के माध्यम से मूर्खतापूर्ण कोड भी पकड़ सकते हैं, if (boolean_var == (1 == 1))जिसके लिए (1 == 1)नोड की बढ़ी हुई प्रकार की जानकारी के लिए धन्यवाद पैटर्न में आता है if (<*> == <boolean_expr>)
कज़

4

व्यावहारिक अंतर कोई नहीं है। 0का मूल्यांकन किया जाता है falseऔर 1इसका मूल्यांकन किया जाता है true। यह तथ्य कि आप बूलियन अभिव्यक्ति का उपयोग करते हैं ( 1 == 1) या 1, परिभाषित करने के लिए true, कोई फर्क नहीं पड़ता है। इन दोनों का मूल्यांकन किया जाता है int

ध्यान दें कि सी मानक पुस्तकालय बूलियन को परिभाषित करने के लिए एक विशिष्ट हेडर प्रदान करता है stdbool.h:।


बेशक आप नहीं हैं ... लेकिन कुछ लोग अन्यथा विशेष रूप से नकारात्मक संख्या के लिए सोच सकते हैं यही कारण है कि :)
Pinkpanther

क्या? आपके पास यह पीछे है। trueका मूल्यांकन किया जाता है 1और falseइसका मूल्यांकन किया जाता है 0। C देशी बूलियन प्रकारों के बारे में नहीं जानता, वे सिर्फ ints हैं।
djechlin

C में, संबंधपरक और समानता ऑपरेटर intमूल्य के साथ 0या प्रकार के परिणाम देते हैं 1। सी में एक वास्तविक बूलियन प्रकार होता है ( _Bool, जिसमें एक मैक्रो boolपरिभाषित होता है <stdbool.h>, लेकिन इसे केवल C99 में जोड़ा गया था, जिसने नए प्रकार का उपयोग करने के लिए ऑपरेटरों के शब्दार्थ को नहीं बदला।
कीथ थॉम्पसन

@djechlin: 1999 मानक के रूप में, सी करता है एक देशी बूलियन प्रकार है। यह कहा जाता है _Bool, और <stdbool.h>है #define bool _Bool
कीथ थॉम्पसन

@KeithThompson, आप के 1 == 1रूप में मूल्यांकन किया जा रहा है के बारे में सही हैं int। संपादित।
जूता

3

हमें सही मूल्य नहीं पता है कि TRUE के बराबर है और संकलक की अपनी परिभाषा हो सकती है। तो क्या आप निजी तौर पर संकलक की परिभाषा के लिए आंतरिक का उपयोग करना है। यह हमेशा आवश्यक नहीं है यदि आपके पास अच्छी प्रोग्रामिंग आदतें हैं लेकिन कुछ खराब कोडिंग शैली की समस्याओं से बच सकते हैं, उदाहरण के लिए:

यदि ((a> b) == TRUE)

यह एक आपदा हो सकती है यदि आप TRUE को मैन्युअल रूप से 1 के रूप में परिभाषित करते हैं, जबकि TRUE का आंतरिक मूल्य एक और है।


सी में, >ऑपरेटर हमेशा सच के लिए 1, झूठ के लिए 0 देता है। किसी भी सी कंपाइलर के इस गलत होने की कोई संभावना नहीं है। समानता की तुलना TRUEऔर FALSEघटिया शैली है; ऊपर स्पष्ट रूप से लिखा गया है if (a > b)। लेकिन विचार है कि अलग सी संकलक सच्चाई का इलाज कर सकते हैं और गलत तरीके से गलत है।
कीथ थॉम्पसन

2
  1. सामग्री सूचीबद्ध करें

आमतौर पर C प्रोग्रामिंग लैंग्वेज में 1 को सही और 0 को गलत के रूप में परिभाषित किया गया है। इसलिए आप निम्नलिखित अक्सर देखते हैं:

#define TRUE 1 
#define FALSE 0

हालाँकि, 0 के बराबर किसी भी संख्या का मूल्यांकन सही और सशर्त विवरण में नहीं किया जाएगा। इसलिए नीचे का उपयोग करके:

#define TRUE (1==1)
#define FALSE (!TRUE)

आप केवल स्पष्ट रूप से दिखा सकते हैं कि जो कुछ भी सच नहीं है, उसे आप झूठे बनाकर सुरक्षित चलाने की कोशिश कर रहे हैं।


4
मैं इसे "इसे सुरक्षित खेलना" नहीं कहूंगा - बल्कि, आप अपने आप को सुरक्षा का गलत अर्थ दे रहे हैं।
dodgethesteamroller
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.