आकार (my_arr) [0] संकलन और समान आकार (my_arr [0]) क्यों करता है?


129

यह कोड क्यों संकलित करता है?

_Static uint32_t my_arr[2];
_Static_assert(sizeof(my_arr) == 8, "");
_Static_assert(sizeof(my_arr[0]) == 4, "");
_Static_assert(sizeof(my_arr)[0] == 4, "");

पहले 2 दावे स्पष्ट रूप से सही हैं, लेकिन मैंने अंतिम पंक्ति के विफल होने की उम्मीद की होगी, क्योंकि मेरी समझ यह है कि sizeof()एक पूर्णांक शाब्दिक का मूल्यांकन करना चाहिए, जिसे एक सरणी के रूप में नहीं माना जा सकता है। दूसरे शब्दों में, यह उसी तरह से विफल होगा जैसे कि निम्न पंक्ति विफल होती है:

_Static_assert(4[0] == 4, "");

दिलचस्प है, निम्नलिखित वास्तव में संकलन करने में विफल रहता है (जो एक ही काम करना चाहिए, नहीं?)

_Static_assert(*sizeof(my_arr) == 4, "");

त्रुटि: अमान्य प्रकार का तर्क '' '' ('लंबे समय से अटूट int') _Static_assert (* sizeof (my_arr) == 4, "");

अगर यह मायने रखता है, मैं 5.3.0 gcc का उपयोग कर रहा हूँ


15
मुझे संदेह है कि ( sizeof( my_arr ) )[ 0 ]विफल रहता है।
एंड्रयू हेनले

हाल के डुप्लिकेट में इस सिंटैक्स आश्चर्य पर एक और भिन्नता है: साइज़ोफ़ (x) ++ संकलन क्यों?
पीटर कॉर्ड्स

जवाबों:


197

sizeofकोई फ़ंक्शन नहीं है। यह एक तरह का संचालक है !या ~

sizeof(my_arr)[0]पार्स के रूप में sizeof (my_arr)[0], जो सिर्फ sizeof my_arr[0]निरर्थक कोष्ठक के साथ है।

यह बिलकुल !(my_arr)[0]पारस की तरह है !(my_arr[0])

सामान्य तौर पर, पोस्टफिक्स ऑपरेटरों की सी। sizeof *a[i]++पर्स में उपसर्ग ऑपरेटरों की तुलना में अधिक पूर्वता होती है sizeof (*((a[i])++))(पोस्टफिक्स ऑपरेटरों के रूप में []और फिर पहले उपसर्ग ऑपरेटरों और ) पर ++लागू होते हैं ।a*sizeof

(यह अभिव्यक्ति का संस्करण है sizeof। एक प्रकार का संस्करण भी है, जो एक कोष्ठक प्रकार का नाम लेता है: sizeof (TYPE)उस स्थिति में परेंस की आवश्यकता होगी और sizeofवाक्य रचना का हिस्सा होगा ।)


14
मुझे निश्चित रूप से पता था कि साइज़ोफ़ एक अपरेंट्री ऑपरेटर था और फ़ंक्शन नहीं, लेकिन पूरी तरह से भूल गया। ओह। विस्तृत विवरण के लिए धन्यवाद। तथ्य यह है कि [] * की तुलना में उच्च पूर्वता है, भले ही दिलचस्प हो।
bgomberg

@melpomene दिलचस्प। मैंने कभी भी sizeofएक अपर संचालक होने के बारे में नहीं सोचा है ।
म्यूटेंटबोर्डबोर्ड

5
क्या आपका मतलब नहीं है "... parses as sizeof (my_arr[0])"? बस एक जगह जोड़ने से वास्तव में कुछ भी नहीं बदलता है।
बर्नहार्ड बार्कर

मैं sizeof((my_array)[0])इसके बजाय की सिफारिश करेंगे
bolov


46

sizeofदो "संस्करण" हैं: sizeof(type name)और sizeof expression। पूर्व को ()अपने तर्क के आसपास एक जोड़ी की आवश्यकता होती है । लेकिन उत्तरार्द्ध - एक तर्क के रूप में एक अभिव्यक्ति के साथ - ()अपने तर्क के आसपास नहीं है। ()आप जो भी तर्क में उपयोग करते हैं, उसे तर्क अभिव्यक्ति के हिस्से के रूप में देखा जाता है, sizeofसिंटैक्स के हिस्से के रूप में नहीं ।

चूंकि my_arrसंकलक को ऑब्जेक्ट नाम के रूप में जाना जाता है, न कि एक प्रकार का नाम, sizeof(my_arr)[0]क्योंकि आपका कंपाइलर वास्तव में sizeofएक अभिव्यक्ति पर लागू होता है:, sizeof (my_arr)[0]जहां (my_arr)[0]तर्क अभिव्यक्ति है। ()आसपास के सरणी नाम विशुद्ध रूप से ज़रूरत से ज़्यादा है। पूरी अभिव्यक्ति के रूप में व्याख्या की है sizeof my_arr[0]। यह आपके पिछले के बराबर है sizeof(my_arr[0])

(इसका मतलब है, BTW, कि आपके पिछले sizeof(my_arr[0])हिस्से में भी एक जोड़ी है ()

यह एक व्यापक रूप से गलत धारणा है कि sizeofवाक्यविन्यास किसी भी तरह ()अपने तर्क के आसपास की एक जोड़ी की आवश्यकता है । इस तरह की अभिव्यक्ति की व्याख्या करते समय यह गलत धारणा लोगों के अंतर्ज्ञान को भ्रमित करती है sizeof(my_arr)[0]


1
पहला संस्करण मौजूद है ताकि आप मशीन पर सामान्य रूप से एक पूर्णांक के आकार की जांच कर सकें (पीछे से जब वहाँ भी बिट-बिट मशीन नहीं थे!), लेकिन intएक वैध अभिव्यक्ति नहीं है, इसलिए आप उपयोग नहीं कर सकते हैं इसके साथ दूसरा रूप।
एनएच।


8

आप sizeofऑपरेटर के संस्करण का उपयोग कर रहे हैं जो एक अभिव्यक्ति को पैरामीटर के रूप में लेता है। एक प्रकार के विपरीत, यह कोष्ठक की आवश्यकता नहीं है। इसलिए, ऑपरेंड बस है (my_arr)[0], जिसमें कोष्ठक निरर्थक हैं।

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