क्यों "आकार (एक? सच: गलत)" चार बाइट्स का आउटपुट देता है?


133

मेरे पास sizeofटर्निरी ऑपरेटर वाले ऑपरेटर के बारे में एक छोटा सा कोड है :

#include <stdio.h>
#include <stdbool.h>

int main()
{
    bool a = true;
    printf("%zu\n", sizeof(bool));  // Ok
    printf("%zu\n", sizeof(a));     // Ok
    printf("%zu\n", sizeof(a ? true : false)); // Why 4?
    return 0;
}

आउटपुट ( GCC ):

1
1
4 // Why 4?

लेकिन यहाँ,

printf("%zu\n", sizeof(a ? true : false)); // Why 4?

टर्नरी ऑपरेटर रिटर्न booleanप्रकार और आकार boolप्रकार 1सी में बाइट है।

फिर चार बाइट का आउटपुट क्यों देता है sizeof(a ? true : false)?


39
sizeof(true)और sizeof(false)4 भी है: ide.geeksforgeeks.org/O5jvuN
tkausl

7
यहाँ और अधिक दिलचस्प सवाल होगा क्यों इस कार्यान्वयन "असंगत" है में यह स्पष्ट रूप से परिभाषित करता है कि _Boolआकार 1, लेकिन नहीं है करने के लिए trueऔर false। लेकिन मानक के पास उस बारे में कहने के लिए कुछ भी नहीं है जहाँ तक मैं बता सकता हूँ।

12
@FelixPalmen एक ही कारण क्यों दिया char a; sizeof(a) == 1और sizeof('a') == sizeof(int)(C में)। यह कार्यान्वयन के बारे में नहीं है, यह भाषा के बारे में है।
एन। 'सर्वनाम' मी।

10
क्या आपने छापने की कोशिश की है sizeof(true)? शायद यह थिन्स को थोड़ा और स्पष्ट कर देगा (विशेष रूप से, यह स्पष्ट हो जाएगा कि टर्नरी ऑपरेटर एक लाल हेरिंग है)।
एन। 'सर्वनाम' मी।

4
@FelixPalmen trueहै #define1 से घ होने के लिए stdbool.hइतना हाँ, इस शाब्दिक परिभाषा है।
एन। 'सर्वनाम' मी।

जवाबों:


223

यह इसलिए है क्योंकि आपके पास है #include <stdbool.h>। वह शीर्षक मैक्रोज़ true और falseहोने 1और होने को परिभाषित करता है0 , इसलिए आपका कथन इस तरह दिखता है:

printf("%zu\n", sizeof(a ? 1 : 0)); // Why 4?

sizeof(int) आपके मंच पर 4 है।


21
"ऐसा इसलिए है क्योंकि आपके पास #include <stdbool.h>" नहीं है, यह नहीं है। sizeof(a ? (uint8_t)1 : (uint8_t)0);4 का परिणाम भी देगा। ऑपरेंड्स का पूर्णांक संवर्धन ?:यहाँ का महत्वपूर्ण हिस्सा है, न कि आकार का trueऔर false
लुंडिन

9
@ लुंडिन: दोनों महत्वपूर्ण हैं। जैसा कि लिखा गया है, प्रकार पहले से ही intबिना प्रचार के है। आप इसे "ठीक" नहीं कर सकते इसका कारण डिफ़ॉल्ट प्रमोशन है।
आर .. गिटहब स्टॉप हेल्पिंग ICE

5
@PeterSchneider यह C ++ नहीं है। यह सी में सी ++ है, trueऔर falseकर रहे हैं नहीं मैक्रो; वे कीवर्ड हैं। वे प्रकार के सही और गलत मूल्यों के होने 1और होने को परिभाषित नहीं करते हैं । 0bool
जस्टिन

5
@PeterSchneider नहीं, आपने आज C के बारे में कुछ सीखा है। दो भाषाओं को भ्रमित न करें। C ++ में, sizeof(true)1. डेमो है
Rakete1111

1
सच है, इसे मिलाया। सावधानी से पढ़ा नहीं गया था और cppreference- लिंक द्वारा गलत किया गया था। मेरी गलती, धन्यवाद। लेकिन मैं सी + + के बारे में यह महसूस कर रहा हूँ।
पीटर श्नाइडर

66

यहाँ, टर्नरी ऑपरेटर रिटर्न booleanप्रकार,

ठीक है, वहाँ अधिक है कि!

सी में, इस टर्नरी ऑपरेशन का परिणाम प्रकार का है int[नीचे नोट्स (1,2)]

इसलिए परिणाम sizeof(int)आपके प्लेटफॉर्म पर अभिव्यक्ति के समान है।


नोट 1: उद्धरण C11, अध्याय .17.18,Boolean type and values <stdbool.h>

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

true

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

false

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

नोट 2: सशर्त ऑपरेटर के लिए, अध्याय :6.5.15, ( जोर मेरा )

पहले ऑपरेंड का मूल्यांकन किया जाता है; इसके मूल्यांकन और दूसरे या तीसरे ऑपरेंड (जो भी मूल्यांकन किया जाता है) के मूल्यांकन के बीच एक अनुक्रम बिंदु है। दूसरे ऑपरेंड का मूल्यांकन केवल तभी किया जाता है जब पहला असमान की तुलना 0 से करता है; तीसरे ऑपरेंड का मूल्यांकन केवल तभी किया जाता है जब पहला 0 के बराबर होता है; परिणाम दूसरे या तीसरे ऑपरेंड (जो भी मूल्यांकन किया जाता है) का मूल्य है, [...]

तथा

यदि दूसरे और तीसरे दोनों ऑपरेंड्स में अंकगणितीय प्रकार है, तो परिणाम प्रकार जो सामान्य अंकगणितीय रूपांतरणों द्वारा निर्धारित किया जाएगा, क्या वे उन दो ऑपरेंडों पर लागू होते थे, परिणाम का प्रकार है। [....]

इसलिए, परिणाम प्रकार पूर्णांक का होगा और मूल्य सीमा के कारण, स्थिरांक प्रकार के ठीक हैं int

उस ने कहा, एक सामान्य सलाह, वास्तव में मानक-अनुरूप int main()होना बेहतर होना चाहिए int main (void)


@ user694733 umm .. क्यों नहीं? <stdbool.h>MACROS को टाइप करने के लिए परिभाषित करता है .. intकि गलत है?
सौरव घोष

@BasileStarynkevitch ठीक है, मुझे लगता है कि अब, यह वास्तव में गलत लगता है, अब अद्यतन किया गया।
सौरव घोष

58

टर्नरी ऑपरेटर एक लाल हेरिंग है।

    printf("%zu\n", sizeof(true));

प्रिंट 4 (या जो कुछ भी sizeof(int)आपके मंच पर है)।

निम्नलिखित मानता है कि boolके लिए एक पर्याय है charया आकार 1 इसी प्रकार की किसी और intसे भी बड़ा है char

कारण है कि sizeof(true) != sizeof(bool)और sizeof(true) == sizeof(int)बस है, क्योंकि trueहै नहीं प्रकार की अभिव्यक्ति bool। यह एक प्रकार की अभिव्यक्ति है int। यह #defineडी के रूप 1में है stdbool.h

boolC में टाइप के कोई भी अंतराल नहीं हैं । intजब भी एक तर्क के रूप में इस्तेमाल किया जाता है, तब भी इस तरह के हर प्रचलन को तुरंत बढ़ावा दिया जाता है sizeofसंपादित करें: यह पैराग्राफ सत्य नहीं है, sizeofप्रचार करने के लिए तर्क नहीं दिए जाते हैं int। हालांकि यह किसी भी निष्कर्ष को प्रभावित नहीं करता है।


अच्छा उत्तर। जब मैंने वर्तमान में सबसे अधिक उत्तर दिए गए उत्तर को पढ़ा, तो मैं सोच रहा था कि सभी कथनों का मूल्यांकन 4 से होना चाहिए। +1
पेड्रो ए

5
(bool)1प्रकार का एक प्रतिद्वंद्विता नहीं है bool?
बेन वोइग्ट

printf("%u\n", sizeof((char) 1));1मेरे मंच पर प्रिंट करता है जबकि printf("%u\n", sizeof(1));प्रिंट 4। क्या इसका यह अर्थ नहीं है कि आपका कथन "प्रत्येक ऐसे प्रचलन को तुरंत int के लिए बढ़ावा दिया जाता है, तब भी जब आकार के तर्क के रूप में उपयोग किया जाता है" गलत है?
योनातन

यह वास्तव में सवाल का जवाब नहीं देता है। आकार और प्रकार trueआदि वास्तव में इस मामले में कोई फर्क नहीं पड़ता ?:क्योंकि यह intकिसी भी तरह पूर्णांक को बढ़ावा देता है । यही है, जवाब को पता होना चाहिए कि ?: एक लाल हेरिंग क्यों है।
लंडिन

6
मुझे लगता है कि उत्तर संभव तरीके से समस्या का समाधान करता है। आप इसे कम करने या सुधारने के लिए स्वागत करते हैं।
एन। 'सर्वनाम' मी।

31

सी में बूलियन प्रकार के बारे में

वर्ष १ ९९९ में सी भाषा में एक बूलियन प्रकार को देर से पेश किया गया था। इससे पहले, सी में एक बूलियन प्रकार नहीं था, बल्कि intसभी बूलियन अभिव्यक्तियों के लिए उपयोग किया जाता था । इसलिए सभी तार्किक ऑपरेटर जैसे कि > == !आदि intमूल्य के 1या वापस लौटाते हैं 0

यह घर-निर्मित प्रकारों का उपयोग करने के लिए अनुप्रयोगों के लिए कस्टम था typedef enum { FALSE, TRUE } BOOL;, जो कि int-sized प्रकारों को भी उबालता है।

C ++ में बहुत बेहतर और स्पष्ट बूलियन प्रकार boolथा, जो 1 बाइट से बड़ा नहीं था। जबकि सी में बूलियन प्रकार या भाव सबसे खराब स्थिति में 4 बाइट्स के रूप में समाप्त होंगे। C ++ के साथ संगतता के कुछ तरीके C99 मानक के साथ C में पेश किए गए थे। सी को फिर बूलियन प्रकार मिला _Boolऔर हेडर भी stdbool.h

stdbool.hC ++ के साथ कुछ अनुकूलता प्रदान करता है। यह हेडर मैक्रो को परिभाषित करता है bool(C ++ कीवर्ड के समान स्पेलिंग) _Bool, जो एक प्रकार का होता है, जो एक छोटा पूर्णांक प्रकार होता है, जिसकी संभावना 1 बाइट होती है। इसी तरह, हेडर दो मैक्रोज़ प्रदान करता है trueऔर false, सी ++ कीवर्ड के समान वर्तनी, लेकिन पुराने सी कार्यक्रमों के लिए पिछड़े संगतता के साथ । इसलिए trueऔर falseविस्तार 1और 0सी में और उनके प्रकार है int। ये मैक्रोज़ वास्तव में बूलियन प्रकार के नहीं होते हैं जैसे कि C ++ कीवर्ड होंगे।

इसी तरह, पिछड़े अनुकूलता प्रयोजनों के लिए, C में तार्किक ऑपरेटर अभी भीint इस दिन तक वापस आते हैं, भले ही आजकल C को एक बूलियन प्रकार मिला हो। C ++ में रहते हुए, तार्किक ऑपरेटर a लौटते हैं bool। इस प्रकार एक अभिव्यक्ति जैसे कि C में a sizeof(a == b)का आकार देगी int, लेकिन boolC ++ में a का आकार ।

सशर्त संचालक के संबंध में ?:

सशर्त ऑपरेटर ?:एक अजीब ऑपरेटर है, जो दो-चौथाई है। यह मानना ​​एक सामान्य गलती है कि यह 100% के बराबर है if() { } else {}। काफी नहीं।

1 और 2 या 3 के ऑपरेंड के मूल्यांकन के बीच एक अनुक्रम बिंदु है। ?:ऑपरेटर की गारंटी है के लिए एक ही या तो 2 या 3 संकार्य का मूल्यांकन, तो यह संकार्य कि मूल्यांकन नहीं किया गया है में से किसी दुष्प्रभाव पर अमल नहीं कर सकते। जैसे कोड true? func1() : func2()निष्पादित नहीं होगा func2()। अब तक सब ठीक है।

हालांकि , एक विशेष नियम है जिसमें कहा गया है कि 2 और 3 के ऑपरेंड को सामान्य रूप से अंकगणितीय रूपांतरणों के साथ एक दूसरे के खिलाफ कथित रूप से प्रचारित और संतुलित होना चाहिए । ( सी में स्पष्ट प्रकार के पदोन्नति नियम यहां बताए गए हैं )। इसका मतलब यह है कि 2 या 3 ओ ऑपरेंड हमेशा कम से कम उतना बड़ा होगा जितना कि ए int

तो यह कोई फर्क नहीं पड़ता है trueऔर सी में falseटाइप का हो सकता intहै क्योंकि अभिव्यक्ति हमेशा कम से कम एक intमामले का आकार देगी ।

यहां तक ​​कि अगर आप अभिव्यक्ति को फिर से लिखेंगे तो भी आकार वापस आ जाएगा !sizeof(a ? (bool)true : (bool)false) int

इसका कारण सामान्य अंकगणितीय रूपांतरणों के माध्यम से निहित प्रकार का प्रचार है।


1
C ++ वास्तव में गारंटी नहीं देता है sizeof(bool)==1
एशेप्लर

1
@aschepler नहीं, लेकिन C ++ मानक के बाहर की वास्तविक दुनिया इसकी गारंटी देती है। एक संकलक का नाम बताइए जहाँ यह 1. नहीं है
लंडिन

नमस्ते। मुझे लगता है कि यह जवाब इसके पहले भाग के बिना बेहतर होगा । दूसरा भाग प्रश्न का उत्तर देता है। बाकी, जबकि दिलचस्प, सिर्फ शोर है।
YSC

@ YSC यह मूल रूप से C और C ++ दोनों को टैग किया गया था, इसलिए उनके विभिन्न बूल प्रकार और उनके पीछे के इतिहास के बीच एक तुलना आवश्यक थी। मुझे संदेह है कि मैंने C ++ टैग के लिए नहीं तो पहला भाग लिखा होगा। हालाँकि, किसी को यह समझना होगा कि sizeof (बूल) 1 क्यों है, लेकिन sizeof (झूठा) C. में 4 है
लुंडिन

21

शीघ्र जवाब:

  • sizeof(a ? true : false)करने के लिए मूल्यांकन करता है 4क्योंकि trueऔर falseमें परिभाषित कर रहे हैं <stdbool.h>के रूप में 1और 0क्रमश: तो अभिव्यक्ति फैलता करने के लिए sizeof(a ? 1 : 0)किस प्रकार के साथ एक पूर्णांक अभिव्यक्ति है int, जो आपके मंच पर 4 बाइट पर है। उसी कारण से, आपके सिस्टम पर sizeof(true)भी मूल्यांकन करेगा 4

हालांकि ध्यान दें कि:

  • sizeof(a ? a : a)मूल्यांकन भी करता है 4क्योंकि टर्नरी ऑपरेटर अपने दूसरे और तीसरे ऑपरेंड पर पूर्णांक प्रचार करता है यदि ये पूर्णांक अभिव्यक्तियाँ हैं। बेशक ऐसा ही होता है sizeof(a ? true : false)और sizeof(a ? (bool)true : (bool)false), लेकिन boolउम्मीद के मुताबिक व्यवहार के रूप में पूरी अभिव्यक्ति की कास्टिंग sizeof((bool)(a ? true : false)) -> 1:।

  • यह भी ध्यान दें कि तुलना ऑपरेटर बूलियन मूल्यों का मूल्यांकन करते हैं 1या 0, लेकिन इसके intप्रकार हैं sizeof(a == a) -> 4:।

बूलियन प्रकृति रखने वाले एकमात्र ऑपरेटर aहोंगे:

  • अल्पविराम ऑपरेटर: दोनों sizeof(a, a)और sizeof(true, a)के रूप में मूल्यांकित 1संकलन समय पर।

  • असाइनमेंट ऑपरेटर: दोनों sizeof(a = a)का sizeof(a = true)मान होता है 1

  • वेतन वृद्धि ऑपरेटर: sizeof(a++) -> 1

अंत में, उपरोक्त सभी केवल C पर लागू होता है: C ++ में boolप्रकार, बूलियन मान trueऔर falseतुलना ऑपरेटर और टर्नरी ऑपरेटर के बारे में अलग-अलग शब्दार्थ हैं : ये सभी sizeof()भाव 1C ++ में मूल्यांकन करते हैं ।


2
अच्छा जवाब जो वास्तव में यह इंगित करने का प्रबंधन करता है कि यह वास्तव में क्या प्रकार है trueऔर क्या नहीं है false, क्योंकि ?:ऑपरेंड intकिसी भी तरह पूर्णांक को बढ़ावा मिलेगा । इस प्रकार sizeof(a ? (uint8_t)true : (uint8_t)false)परिणाम के रूप में भी 4 उपज होगी।
लुंडिन

यह उत्तर मुख्य महत्वपूर्ण बिंदु को कवर करता है, मूल्य को बढ़ावा दिया जाता हैint
चिननी 19

1

यहाँ एक स्निपेट है जिससे स्रोत में शामिल किया गया है

#ifndef __cplusplus

#define bool    _Bool
#define true    1
#define false   0

#else /* __cplusplus */

वहाँ मैक्रोज़ trueऔर falseक्रमशः 1 और 0 घोषित किए जाते हैं।

हालांकि इस मामले में प्रकार शाब्दिक स्थिरांक का प्रकार है। 0 और 1 दोनों पूर्णांक स्थिरांक हैं जो एक इंट में फिट होते हैं, इसलिए उनका प्रकार इंट है।

और sizeof(int)आपके मामले में 4 है।


-3

सी में कोई बूलियन डेटाटाइप नहीं है, इसके बजाय तार्किक अभिव्यक्तियाँ पूर्णांक मानों का मूल्यांकन करती हैं, 1अन्यथा सच है0

सशर्त भाव की तरह if, for, while, या c ? a : bएक पूर्णांक उम्मीद करते हैं, यदि संख्या गैर शून्य यह माना जाता है है trueकुछ विशेष मामलों के अलावा, यहाँ एक पुनरावर्ती योग समारोह जिसमें त्रिगुट ऑपरेटर का मूल्यांकन करेंगे है trueजब तक nपहुंच 0

int sum (int n) { return n ? n+sum(n-1) : n ;

इसका उपयोग NULLपॉइंटर की जांच करने के लिए भी किया जा सकता है , यहां एक पुनरावर्ती कार्य है जो सिंगली-लिंक्ड-लिस्ट की सामग्री को प्रिंट करता है।

void print(sll * n){ printf("%d -> ",n->val); if(n->next)print(n->next); }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.