2011-05-09 12 views
8

मैं सी में एक अंतिम कल के लिए अध्ययन कर रहा हूँ, और sizeof ऑपरेटर से संबंधित प्रश्न है।sizeof सरणी स्पष्टीकरण

मान लें कि int का आकार 32 बिट्स है और एक सूचक 64 बिट्स है।

अगर वहाँ एक समारोह थे:

int 
foo (int zap[]) 
{ 
    int a = sizeof(zap); 
    return a; 
} 

क्योंकि zap एक सूचक है, foo8 वापसी होगी, के रूप में है कि कितने बाइट्स इस विशेष सूचक स्टोर करने के लिए आवश्यक हैं। हालांकि, निम्न कोड के साथ:

int zip[] = { 0, 1, 2, 3, 4, 5 }; 
int i = sizeof(zip); 

i होगा 6 * sizeof(int) = 6 * 4 = 24

क्यों है यह है कि sizeof(zip) रिटर्न तत्वों की संख्या बार प्रत्येक तत्व के आकार, जबकि sizeof(zap) एक के आकार देता है सूचक? क्या यह zap का आकार निर्दिष्ट नहीं है, और zip नहीं है? संकलक जानता कि zip है 6 तत्वों, लेकिन कितनी बड़ी zap हो सकता है के रूप में एक सुराग नहीं है।

उत्तर

8

यह सी वाक्य रचना में एक विषमता की तरह है। सी में किसी फ़ंक्शन में सरणी को पास करना संभव नहीं है, इसलिए जब आप पैरामीटर में से किसी एक के लिए फ़ंक्शन घोषणा में सरणी सिंटैक्स का उपयोग करते हैं तो संकलक इसे पॉइंटर के रूप में पढ़ता है।

सी में अधिकांश मामलों में जब आप किसी अभिव्यक्ति में सरणी का उपयोग करते हैं तो सरणी को अपने पहले तत्व में एक सूचक में रूपांतरित किया जाता है और यह वही होता है जब आप फ़ंक्शन को कॉल करते हैं। निम्नलिखित कोड में:

int bar[] = {1,2,3,4}; 
foo(bar); 

सरणी पहला तत्व के लिए सूचक में बदल जाती है और उस समारोह क्या प्राप्त करता है।

निषेध रूपांतरण का यह नियम हमेशा लागू नहीं होता है। जैसा कि आपने उदाहरण के लिए खोजा है sizeof ऑपरेटर सरणी पर काम करता है, और यहां तक ​​कि & (पता-ऑफ) ऑपरेटर मूल सरणी पर काम करता है (यानी sizeof(*&bar) == 4*sizeof(int))।

सी में एक फ़ंक्शन पैरामीटर के रूप में एक सरणी प्राप्त नहीं कर सकता है, यह केवल पहले तत्व को पॉइंटर प्राप्त कर सकता है, या किसी सरणी के लिए पॉइंटर प्राप्त कर सकता है ... या आपको सरणी को संरचना में लपेटना होगा।

भले ही आप समारोह घोषणा में कोष्ठक के बीच एक संख्या डाल ...

void foo(int x[4]) 
{ 
    ... 
} 

कि संख्या पूरी तरह से संकलक द्वारा नजरअंदाज कर दिया है ... संकलक के लिए है कि घोषणा पूरी तरह से

के बराबर है
void foo(int *x) 
{ 
    ... 
} 

और उदाहरण के लिए भी यह बुला एक अलग आकार के साथ एक सरणी गुजर किसी भी त्रुटि पैदा नहीं होगा ...

int tooshort[] = {1,2,3}; 
foo(tooshort); /* Legal, even if probably wrong */ 

(वास्तव में एक संकलक एक चेतावनी दे सकता है, लेकिन पूरी तरह से कोड कानूनी सी है और अगर संकलक मानक इस प्रकार स्वीकार किया जाना चाहिए) यदि आपको लगता है कि जब समारोह तर्क में अजीब है सरणियों के बारे में इस नियम

तो मैं सहमत हूं, लेकिन इस तरह सी भाषा परिभाषित की गई है।

+0

संकलक द्वारा int को अनदेखा नहीं किया गया है, int x [4] फ़ंक्शन पैरामीटर के रूप में इसका अर्थ है कि आपको _exactly_ 4 तत्वों का सरणी पॉइंटर पास करना होगा। यह कोड में 'int (* x) [4]' कहीं और लिखने जैसा ही है। इसके अलावा, यह उत्तर समस्या को इंगित करता है: पैरामीटर के लिए सरणी वाक्यविन्यास का प्रोग्राम में कहीं और घोषित एरे के लिए एक अलग अर्थ है। यह सी भाषा की डंबर "विशेषताओं" में से एक है। भ्रम से बचने के लिए, पैरामीटर के लिए हमेशा 'int * x' नोटेशन का उपयोग करें। – Lundin

+0

क्या आप इंगित कर सकते हैं कि मानक में लिखा गया है कि ब्रैकेट के बीच की संख्या पास सरणी के आकार के बराबर होनी चाहिए? संकेत: यह एक अजीब आवश्यकता होगी कि आप एक सरणी पारित नहीं कर सकते हैं और कार्य वास्तव में केवल एक सूचक प्राप्त करता है। 'Foo (bar)' के साथ फ़ंक्शन को कॉल करते समय, जहां 'बार' एक सरणी है जिसे सरणी पहले से ही एक सूचक में परिवर्तित कर दिया गया है ** यहां तक ​​कि कंपाइलर के लिए ** फ़ंक्शन कॉल माना जाता है। किसी आकार की जानकारी पर सीमा लागू करने का कोई मतलब नहीं होगा जो रूपांतरण में पहले से ही गिरा दिया गया है। – 6502

+0

@ लंदन, सरणी पैरामीटर के पहले आयाम के लिए नहीं, 4 को अनिवार्य रूप से अनदेखा किया जाता है। सी 99 में कीवर्ड के 'स्थिर' की संभावना है, यह निर्दिष्ट करने के लिए कि कार्य * कम से कम * वस्तुओं के लिए अपेक्षित है। लेकिन अभी भी पैरामीटर का प्रकार 'int *' है। –

2

क्योंकि जिप एक सरणी है और संकलक संकलन समय पर इसके आकार को जानता है। यह सिर्फ सी में काफी सामान्य दो अलग बातें, कुछ के लिए एक ही अंकन का उपयोग का मामला

int 
foo (int zap[]) 

किसी भी विचार नहीं है पूरी तरह से

int 
foo (int *zap) 

संकलक के बराबर है कितना बड़ा जैप सकता है हो (इसलिए यह प्रोग्रामर को खोजने का कार्य छोड़ देता है)।

+1

इस पर सी एफएसी ** अमूल्य ** है: http://c-faq.com/aryptr/index.html – cnicutar

+0

भले ही आप ब्रैकेट के बीच कोई संख्या डालते हैं, फिर भी यह अभी भी एक सूचक और संख्या है खुद को संकलक द्वारा पूरी तरह से अनदेखा किया जाता है। तो यह संकलक के बारे में कोई समस्या नहीं है जो आकार को नहीं जानता ... यह कि सी भाषा में फ़ंक्शन तर्क सूचियों में सरणी के बारे में एक विशेष अजीब नियम है। – 6502

+0

@ 6502 आप सही, अच्छी कॉल कर रहे हैं। ब्रैकेट में एक संख्या डालने से वही प्रभाव होगा, यही कारण है कि यह दृढ़ता से निराश है। – cnicutar

-1

क्योंकि यह स्थिर 6 elemens साथ प्रारंभ किया गया है।

+0

कोई डाउनवोट स्पष्टीकरण देना चाहता है? मेरा जवाब 2 अन्य लोगों के समान है, बस थोड़ा और संक्षिप्त ?? –

+0

मैंने डाउनवोट नहीं किया, लेकिन इससे कोई फर्क नहीं पड़ता कि "ज़िप" प्रारंभ किया गया था या नहीं। मुद्दा सी के अजीब फ़ंक्शन पैरामीटर सिंटैक्स के बारे में है। – Lundin

0

zip का आकार संकलन समय पर ज्ञात है और zap का आकार नहीं है। यही कारण है कि आप sizeof(zap) पर पॉइंटर का आकार और sizeof(zip) पर सरणी का आकार प्राप्त कर रहे हैं।

2

zip6 * sizeof(int) का मेमोरी ब्लॉक है, इसलिए इसका आकार 24 (आपके आर्किटेक्चर पर) है। zap (यह आपके समारोह घोषणा में int *zap रूप में लिखा जा सकता है) फिर भी किसी भी स्मृति पते को इंगित कर सकते और संकलक जानते हुए भी कितनी जगह इस पर शुरू (या यहां तक ​​युक्त इस) पता आबंटित की गई है का कोई रास्ता नहीं है।

0

संकेत करने के लिए कुछ स्थितियों wherearrays क्षय रहे हैं। फंक्शन कॉल उनमें से एक है।

संबंधित मुद्दे