क्या सी मानक स्पष्ट रूप से 0 या 1 के रूप में सत्य मान दर्शाता है?


86

हम जानते हैं कि कोई भी संख्या जो कि बराबर नहीं है सी में 0देखी जाती trueहै, इसलिए हम लिख सकते हैं:

int a = 16;

while (a--)
    printf("%d\n", a);  // prints numbers from 15 to 0

हालांकि, मैं सोच है कि क्या सही / गलत रूप में परिभाषित कर रहे हैं था 1/ 0सी में तो मैं नीचे दिए गए कोड की कोशिश की:

printf("True = %d, False = %d\n", (0 == 0), (0 != 0));  // prints: True = 1, False = 0

क्या C मानक स्पष्ट रूप 1से 0क्रमशः और सत्य के सत्य मूल्यों को इंगित करता है ?


3
मुझे लगता है कि यह एसओ प्रश्न प्रासंगिक है
इमरान अली

3
मैं इस के तहत चलाने की कोशिश gccके साथ -std=c89और यह एक ही परिणाम प्राप्त होते हैं।
केविन डोंग

1
@ ब्लेकहोल, 15 से 0. तक
आर्टुरो टॉरेस सैंचेज़

6
लगभग डुबकी लेकिन एक दशक से पहले एसओ / एसई: c-faq.com/bool/bool2.html
dave_thompson_085

1
यह गलत है कि शून्य कैनन है, हालांकि सच में आमतौर पर "शून्य नहीं" के रूप में सोचा जाता है। प्रोग्रामर होने के नाते वे हालांकि, हम सभी ने अपने विभिन्न कारणों से 1 का उपयोग "शून्य नहीं" के रूप में किया है। आपको एक सच्चे पर भरोसा करने के लिए प्रोत्साहित नहीं किया जाता है कि वास्तव में ठीक है 1. जबकि (0 == 0) आपके उदाहरण में एक है, जैसे कुछ (12 == 12) आसानी से मान सकते हैं जैसे कि मूल्य 12; "सच" भी।
इंजीनियर

जवाबों:


96

सी मानक स्पष्ट रूप से की सच्चाई मूल्यों का द्योतक नहीं है trueऔर falseके रूप में 0और 1क्रमशः?

सी मानक परिभाषित करता है trueऔर falseमैक्रोज़ के रूप में stdbool.hजिसमें क्रमशः 1और विस्तार होता 0है।

C11-§7.18:

शेष तीन मैक्रो #ifप्रीप्रोसेसिंग निर्देशों में उपयोग के लिए उपयुक्त हैं । वो हैं

true

जो पूर्णांक स्थिरांक तक फैलता है 1,

false

जो पूर्णांक स्थिरांक तक फैलता है 0[...]

ऑपरेटरों के लिए ==और !=, मानक कहते हैं

C11-§6.5.9 / 3:

==(के बराबर) और !=(नहीं के बराबर) ऑपरेटरों उनके कम पूर्वता के अलावा संबंधपरक ऑपरेटर के अनुरूप हैं। 108) प्रत्येक ऑपरेटर पैदावार देता है 1यदि निर्दिष्ट संबंध सही है और 0यदि यह गलत है। परिणाम प्रकार है int। किसी भी जोड़े के लिए, वास्तव में संबंधों में से एक सच है।


20
यह मुझे लगता है कि सवाल के बारे में है 0 == 0और 0 != 0आदि, मैक्रोज़ का मूल्य नहीं है।
एमएम

9
मुझे लगता है कि जब उन्होंने लिखा था trueतो उनका मतलब था "एक वास्तविक तुलना का मूल्य" या कुछ और, मैक्रो नहींtrue
एमएम

1
@KevinDong; हां, C99 ड्राफ्ट में समान पैराग्राफ है।
haccks

1
@ झटके: आप बिना किसी संकोच के इसके बारे में कह सकते हैं "समान" जब मैंने जरूरत पड़ने पर c99 को संदर्भित किया तो मैंने पैराग्राफ को देखने के लिए बहुत अधिक आलसी था क्योंकि मैंने आपकी बोली को बढ़ा दिया था। और मैं इसे खोजने में सक्षम था बस इसे ctrl+ के माध्यम से खोज f;)
dhein

2
@MingDuck: NaN == NaNगलत है और NaN != NaNसच है। उस कथन से कोई समस्या नहीं है।
kennytm

51

यह C11 में स्पष्ट रूप से इंगित नहीं किया गया है। सभी भाषा-स्तरीय ऑपरेशन 1 सत्य के रूप में वापस आएंगे (और NaN सहित किसी भी गैर-सच को स्वीकार करेंगे)।

  • यदि आप चिंता करते हैं _Bool, तो सत्य 1 होना चाहिए क्योंकि मानक को केवल 0 और 1. को रखने की आवश्यकता होती है (§6.2.5 / 2)।
  • इसके अलावा में <stdbool.h>मैक्रो trueको फैलता है 1(§7.18 / 3)
  • ==, !=, <, >, <=और >=लौट 0 या 1 (§6.5.8 / 6, §6.5.9 / 3)।
  • !, &&और ||वापसी 0 या 1 (§6.5.3.3 / 5, .16.5.13 / 3, /6.5.14 / 3)
  • defined 0 या 1 तक फैलता है (§6.10.1 / 1)

लेकिन सभी मानक लाइब्रेरी फ़ंक्शंस जैसे islowerकि सत्य के लिए केवल "नॉनज़रो" कहते हैं (उदाहरण के लिए .17.4.1 / 1, .17.17.5.1 / 3, .7.30.2.1 / 1, §7.30.2.2.1 / 4)।


§6.2.5 / 2 : प्रकार के रूप में घोषित एक वस्तु _Bool0 और 1 मूल्यों को संग्रहीत करने के लिए पर्याप्त बड़ी है।

§6.5.5.3 / 5 : तार्किक निषेध ऑपरेटर !का परिणाम 0 है यदि इसके ऑपरेंड का मूल्य असमान की तुलना 0, 1 से करता है यदि इसके ऑपरेंड का मान 0. के बराबर होता है ...

§6.5.8 / 6 : प्रत्येक ऑपरेटर <(इससे कम), >(अधिक से अधिक), <=(इससे कम या बराबर), और >=(अधिक से अधिक बराबर) 1 प्राप्त होगा यदि निर्दिष्ट संबंध सत्य है और 0 यदि गलत है। 107)…

§6.5.9 / 3 : ==(उनके बराबर) और !=(ऑपरेटरों के बराबर नहीं) ऑपरेटर रिलेशनल ऑपरेटरों के अनुरूप होते हैं, उनके निचले पूर्वक्रम के सिवाय। 10.8 प्रत्येक ऑपरेटर पैदावार 1 देता है यदि निर्दिष्ट संबंध सही है और 0 यदि यह है तो असत्य। ...

§6.5.13 / 3 : यदि &&ऑपरेटर अपने दोनों ऑपरेशंस की तुलना असमान 0 से करता है, तो उसे 1 प्राप्त होगा; ...

§6.5.14 / 3 : ||ऑपरेटर 1 का उत्पादन करेगा यदि उसके किसी भी ऑपरेंड ने असमान की तुलना 0 से की है; ...

§6.10.1 / 1 : ... इसमें फॉर्म के अपर ऑपरेटर संचालक भाव हो सकते हैं - defined identifier- या defined ( identifier )- जो कि 1 का मूल्यांकन करते हैं ...

§7.4.1 (चरित्र वर्गीकरण कार्य) / 1 : इस उप- धारा में कार्य नॉनज़रो ( सही) लौटाते हैं यदि और केवल ...

§7.18 / 3 : शेष तीन मैक्रो #ifप्रीप्रोसेसिंग निर्देशों में उपयोग के लिए उपयुक्त हैं । वे हैं - true- जो पूर्णांक स्थिरांक 1,…

§7.17.5.1 / 3 : atomic_is_lock_freeजेनेरिक फ़ंक्शन नॉनज़रो (सच्चा) लौटाता है यदि और केवल तभी जब ऑब्जेक्ट का संचालन लॉक-फ़्री हो। ...

§7.30.2.1 (वाइड कैरेक्टर वर्गीकरण फ़ंक्शंस) / 1 : इस सबक्लोज़ में फ़ंक्शंस नॉनज़रो ( ट्रू) लौटाते हैं यदि और केवल यदि…

§7.30.2.2.1 / 4 : iswctypeफ़ंक्शन नॉनज़रो (सच्चा) लौटाता है यदि और केवल यदि…


23

मानक के दो क्षेत्र हैं जिन्हें आपको बूलियन मानों से निपटने के बारे में पता होना चाहिए (जिसके द्वारा मैं सी में विशिष्ट सी bool/_Boolप्रकार के बजाय सही / गलत मूल्यों का अर्थ करता हूं )।

पहले को अभिव्यक्ति के परिणाम के साथ करना पड़ता है और C11 6.5 Expressions(उदाहरण के लिए, संबंधपरक और समानता ऑपरेटरों) के विभिन्न भागों में पाया जा सकता है । लब्बोलुआब यह है कि, जब भी एक बूलियन मूल्य एक अभिव्यक्ति द्वारा उत्पन्न होता है, तो ...

... पैदावार 1 है यदि निर्दिष्ट संबंध सत्य है और 0 यदि यह गलत है। परिणाम का प्रकार int है।

तो, हाँ, किसी भी बूलियन-जनरेटिंग अभिव्यक्ति का परिणाम सही के लिए एक होगा, या झूठे के लिए शून्य होगा। यह उस चीज़ से मेल खाता है जो आपको stdbool.hमानक मैक्रोज़ में मिलेगी trueऔर falseउसी तरह परिभाषित की जाएगी।

हालांकि यह ध्यान रखें कि, "आप जो भेजते हैं उसमें उदारवादी हों, जो आप स्वीकार करते हैं उसमें उदारता रखें" के दृढ़ता सिद्धांत का पालन करते हुए, बूलियन संदर्भ में पूर्णांकों की व्याख्या कुछ अधिक आराम से होती है।

फिर से, के विभिन्न भागों से 6.5, आप इस तरह की भाषा देखेंगे:

||ऑपरेटर 1 उपज जाएगा अगर इसकी ऑपरेंड के या तो 0 करने के लिए असमान तुलना; अन्यथा, इसकी पैदावार 0. परिणाम का प्रकार int है।

उस (और अन्य भागों) से, यह स्पष्ट है कि शून्य को गलत माना जाता है और कोई अन्य मूल्य सत्य है।


एक तरफ के रूप में, बूलियन पीढ़ी और व्याख्या के लिए किस मूल्य का उपयोग किया जाता है यह निर्दिष्ट करने वाली भाषा भी C99 और C89 में वापस दिखाई देती है, इसलिए वे काफी समय से आसपास हैं। यहां तक ​​कि K & R (ANSI-C दूसरा संस्करण और पहला संस्करण) निर्दिष्ट किया गया है, जैसे कि टेक्स्ट सेगमेंट:

संबंधपरक भाव जैसे कि i > jऔर तार्किक भाव जुड़े हुए हैं &&और यदि सही है, और यदि गलत है, तो ||उन्हें परिभाषित किया गया है ।10

की कसौटी पर भाग में if, while, for, आदि, "सही" बस का अर्थ है "गैर शून्य"।

&&ऑपरेटर ... रिटर्न 1 यदि दोनों अपनी ऑपरेंड शून्य, 0 अन्यथा करने के लिए असमान की तुलना करें।

||ऑपरेटर ... अन्यथा रिटर्न 1 यदि या तो अपने ऑपरेंड शून्य करने के लिए असमान तुलना, और 0।

मैक्रोज़ stdbool.hवापस C99 में भी दिखाई देते हैं, लेकिन C89 या K & R में नहीं, क्योंकि हेडर फ़ाइल उस बिंदु पर मौजूद नहीं थी।


2
ध्यान दें कि ||, ==, !=आदि उपज int, कोई बूलियन प्रकार
एम एम

2
मैं इस सवाल को सही के लिए वोट करता हूं। मेरे लिए सवाल रिलेशनल ऑपरेटर्स के बारे में है न कि मैक्रों के बारे में।
crruczek

"की कसौटी पर भाग में if, while, for, आदि," सही "बस का अर्थ है" गैर शून्य "।" यह जवाब का मुख्य हिस्सा है और मेरी राय में, बहुत पहले से डेनिस रिची का दुर्भाग्यपूर्ण विकल्प है। कोई भी व्यक्ति जिसने फ़ंक्शन लिखा है जो त्रुटि कोड को रिटर्न मान के रूप में देता है #define noErr 0और किसी भी गैर-शून्य त्रुटि कोड एक त्रुटि है। और फिर समस्या यह है कि सादगी और सुंदरता if ( ready_to_do_something() ){do_something();} काम नहीं करती है। यह होना है if ( !not_ready_to_do_something() ){do_something();}"कई झूठ हैं, लेकिन केवल एक सच्चाई है।" TRUE 0. होना चाहिए
रोबर्ट ब्रिस्टो-जॉनसन

जिज्ञासा से बाहर, C नियमों के पहले ड्राफ्ट ने "&&" और "" के व्यवहार को कैसे निर्दिष्ट किया? उस स्थिति में जहां ऑपरेंड्स में 0 या 1 के अलावा अन्य मूल्य थे? आपके द्वारा उद्धृत पाठ "& quot; और" से जुड़े "लॉजिकल एक्सप्रेशंस" कहता है, लेकिन क्या होगा यदि वे ऑपरेटर लॉजिकल एक्सप्रेशंस के अलावा अन्य चीजों को कनेक्ट करते हैं?
सुपरकैट

1
@sdenham, हाँ। K & R I की पहली प्रतिलिपि में (पहला संस्करण, प्रिंट रन 14, एक इतनी जल्दी कि इसमें चार विशिष्ट मशीनों की हार्डवेयर विशेषताओं का उल्लेख है, PDP-11, हनीवेल -6000, IBM-370 और इंटरडाटा -8 / 32) A.7.6/7/10/11(संबंधपरक / समानता / तार्किक / और / तार्किक-या) सभी निर्दिष्ट करते हैं कि यह परिणाम के रूप में 0 या 1 देता है। इसमें शामिल करने के लिए अद्यतन उत्तर दिया है।
पैक्सिडाब्लो

10

आप कई अलग-अलग चीजों का मिश्रण कर रहे हैं: बयानों, ऑपरेटरों और बूलियन प्रकारों को नियंत्रित करें। प्रत्येक के अपने नियम हैं।

नियंत्रण कथन, उदाहरण के लिए ifकथन C11 6.4.8.1 की तरह काम करते हैं :

दोनों रूपों में, पहले सबस्टेशन को निष्पादित किया जाता है यदि अभिव्यक्ति असमान की तुलना 0 से करती है।

while, forआदि का एक ही नियम है। इसका "सत्य" या "असत्य" से कोई लेना-देना नहीं है।

माना जाता है कि ऑपरेटरों के लिए एक बूलियन परिणाम उपज रहे हैं, वे वास्तव में intमूल्य 1 या 0. के साथ उपज कर रहे हैं । उदाहरण के लिए समानता ऑपरेटरों, C11 6.5.9:

प्रत्येक ऑपरेटर 1 पैदावार देता है यदि निर्दिष्ट संबंध सही है और 0 झूठे होने पर

उपरोक्त सभी इसलिए है क्योंकि वर्ष 1999 तक C का बूलियन प्रकार नहीं था, और जब यह एक हो गया, तब भी उपरोक्त नियमों को नहीं बदला गया था। इसलिए अधिकांश अन्य प्रोग्रामिंग भाषाओं के विपरीत, जहां स्टेटमेंट और ऑपरेटर्स एक बूलियन प्रकार (जैसे सी ++ और जावा) का उत्पादन करते हैं, वे सिर्फ intएक मूल्य शून्य या शून्य नहीं के साथ उपज देते हैं । उदाहरण के लिए, sizeof(1==1)C में 4 देंगे लेकिन C ++ में 1।

सी में वास्तविक बूलियन प्रकार का नाम दिया गया है _Boolऔर एक आधुनिक संकलक की आवश्यकता है। हैडर stdbool.hपरिभाषित करता है मैक्रो bool, trueऔर false, कि का विस्तार _Bool, 1और 0(के साथ सी ++ संगतता के लिए) क्रमशः।


हालांकि इसे नियंत्रण कथनों और ऑपरेटरों के इलाज के लिए अच्छी प्रोग्रामिंग प्रैक्टिस माना जाता है, क्योंकि उन्हें वास्तव में बूलियन प्रकार की आवश्यकता होती है। MISRA-C जैसे कुछ कोडिंग मानक इस तरह के अभ्यास की सलाह देते हैं। अर्थात्:

if(ptr == NULL)के बजाय if(ptr)

if((data & mask) != 0)के बजाय if(data & mask)

इस तरह की शैली का उद्देश्य स्थिर विश्लेषण उपकरणों की सहायता से प्रकार की सुरक्षा को बढ़ाना है, जो बदले में बग को कम करता है। यकीनन, यह शैली तभी सार्थक है जब आप स्थैतिक विश्लेषणकर्ताओं का उपयोग करते हैं। हालांकि कुछ मामलों में यह अधिक पठनीय, स्व-दस्तावेजीकरण कोड की ओर जाता है, उदाहरण के लिए

if(c == '\0') 

अच्छा है, आशय स्पष्ट है, कोड स्व-दस्तावेजीकरण है।

बनाम

if(c) 

खराब। कुछ भी मतलब हो सकता है, और हमें cकोड को समझने के प्रकार की तलाश में जाना होगा । यह एक पूर्णांक, एक सूचक या एक चरित्र है?


1
sizeof(bool)C ++ में कार्यान्वयन विशिष्ट है। Stackoverflow.com/questions/4897844/is-sizeofbool-defined देखें ।
डेविड हैमेन

@David Hammen बस आकार के रूप में (0 == 0) कार्यान्वयन-परिभाषित भी है। यह सिर्फ एक उदाहरण है।
लुंडिन

मैंने सोचा कि सी ने बुलियन प्रकार के नियमों को बदल दिया। अन्य प्रकार के uintN प्रकार (कई पुराने संकलक ("बिट" प्रकार सहित) एक मान के निचले N बिट्स को संग्रहीत करते हैं और किसी भी उच्च बिट्स को अनदेखा करते हैं, जबकि नए बुलियन प्रभावी ढंग से "या" सभी बिट्स को एक साथ जोड़ते हैं।
सुपरकैट

1
ऐसा होना चाहिए if(ptr != NULL), या शायद if(!ptr)?
मैथ्यू के।

1
if(c == '\0')कोडिंग की विशेष रूप से सामान्य शुरुआती गलती के लिए खुद को उधार देता है if(c = '\0'), इसलिए मैं इससे बचता हूं। सहमत, if(c)बुरा है ... यह होना चाहिए, उदाहरण के लिए,if(valveIsOpen)
आजा

4

मैंने कई भाषाओं में प्रोग्राम किया है। मैंने देखा है कि यह भाषा के आधार पर सच 1 या -1 है। 1 सही होने के पीछे तर्क यह था कि या तो एक 0 था या 1. सच होने के पीछे तर्क -1 था! ऑपरेटर एक का पूरक था। इसने सभी 1 के 0 को बदल दिया और सभी 0 के 1 को एक इंट में। तो, एक इंट के लिए; 0 = -1 और! (- 1) = 0. इसने मुझे काफी उलझा दिया है कि मैं किसी चीज़ की तुलना == सच नहीं करता, बल्कि इसकी तुलना करता हूँ! = झूठा। इस तरह, मेरी प्रोग्रामिंग शैली हर भाषा में काम करती है। तो मेरा जवाब है कि इसके बारे में चिंता न करें, लेकिन प्रोग्राम करें ताकि आपका कोड सही तरीके से काम करे।


कैसे ! सभी को 0 में बदलें और फिर भी 5 के लिए उत्पादन करें!
कोडेशोत

@ कोडोडॉट यह नहीं हो सकता। लेकिन वह जो बिंदु बना रहा है, वह यह है कि सभी भाषाएं इसके संचालन का इलाज नहीं करती हैं! एक बूलियन के रूप में। कुछ इलाज! C के ~ के रूप में - यह एक बिटवाइज़ पूरक है। जिस स्थिति में, परिणामी मूल्य को निर्धारित करने के लिए पहले स्थान पर चर के प्रकार को जानने की आवश्यकता होती है, इसलिए! (Uint32_t) 5 4,294,967,290 होगा। लेकिन 0 अभी भी 4,294,967,295, और 4,294,967,295 सत्य है।
पेगासस एप्सिलॉन

1

इस जवाब को थोड़ा और बारीकी से देखने की जरूरत है।

C ++ में वास्तविक परिभाषा यह है कि कुछ भी नहीं 0 को सच माना जाता है। यह प्रासंगिक क्यों है? क्योंकि C ++ नहीं जानता है कि एक पूर्णांक क्या है जिसके बारे में हम उसके बारे में सोचते हैं - हम इसका अर्थ बनाते हैं, यह सभी का अर्थ है कि इसका अर्थ क्या है, इसके लिए शेल और नियम हैं। यह जानता है कि बिट्स क्या हैं, जो एक पूर्णांक बनाते हैं।

1 के रूप में पूर्णांक बिट्स में शिथिल रूप से दर्शाया जाता है, 0000 0001 के रूप में 8-बिट हस्ताक्षरित int कहते हैं। कई बार हम जो देखते हैं वह थोड़ा झूठ है, -1 हस्ताक्षरित प्रकृति के कारण इसे दर्शाने का एक अधिक सामान्य तरीका है 'पूर्णांक' का। 1 वास्तव में सही मतलब नहीं हो सकता, क्यों? क्योंकि यह 1111 1110 ऑपरेशन नहीं है। यह एक बूलियन के लिए एक बहुत बड़ा मुद्दा है। जब हम एक बूलियन के बारे में बात करते हैं, तो यह सिर्फ 1 बिट है - यह वास्तव में सरल है, 0 गलत है और 1 सच है। सभी तर्क संचालन तुच्छ के रूप में हैं। यही कारण है कि पूर्णांक (हस्ताक्षरित) के लिए '-1' को 'सत्य' के रूप में नामित किया जाना चाहिए। 1111 1111 NOT'ed हो जाता है 0000 0000 --- तर्क रखता है और हम अच्छे हैं। अनसाइन्टेड इन्ट्स थोड़ा मुश्किल है और अतीत में आमतौर पर बहुत अधिक उपयोग किया जाता है - जहां 1 का मतलब सच है क्योंकि यह तर्क का अर्थ लगाना आसान है कि '

यही स्पष्टीकरण है। मैं कहता हूं कि स्वीकृत उत्तर गलत है - सी / सी ++ परिभाषा में कोई स्पष्ट परिभाषा नहीं है। एक बूलियन एक बूलियन है, आप एक पूर्णांक को बूलियन के रूप में मान सकते हैं, लेकिन तथ्य यह है कि आउटपुट एक पूर्णांक कहता है कि वास्तव में किए जा रहे ऑपरेशन के बारे में कुछ भी नहीं है।


4
प्रश्न C के बारे में था, C ++ के बारे में नहीं।
ग्लोगल

0

यह आपके printfबयान में रिलेशनल ऑपरेटर्स के कारण हुआ ।

संचालक ==और संचालक!=

चूंकि (0 == 0)यह सच है, इसलिए यह एक मूल्य देता है1

जबकि, (0 != 0)यह सच नहीं है, एक मूल्य देता है 0

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.