2010-06-01 11 views
26

पूरा उदाहरण:सी-एरे के पास फ़ंक्शन में पास होने पर गलत आकार() मान क्यों होता है?

#include <stdio.h> 

void test(int arr[]) { 
    int arrSize = (int)(sizeof(arr)/sizeof(arr[0])); 
    printf("%d\n", arrSize); // 2 (wrong?!) 
} 

int main (int argc, const char * argv[]) { 
    int point[3] = {50, 30, 12}; 

    int arrSize = (int)(sizeof(point)/sizeof(point[0])); 
    printf("%d\n", arrSize); // 3 (correct :-)) 

    test(point); 

    return 0; 
} 

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

उत्तर

37

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

आप समारोह की जरूरत है सरणी के आकार का पता करने के लिए, आप इसे एक अलग पैरामीटर के रूप में पारित करना चाहिए:

void test(int arr[], size_t elems) { 
    /* ... */ 
} 

int main(int argc, const char * argv[]) { 
    int point[3] = {50, 30, 12}; 
    /* ... */ 
    test(point, sizeof(point)/sizeof(point[0])); 
    /* ... */ 
} 

भी ध्यान रखें कि, एक ऐसी ही कारण (sizeof एक सूचक ले रही है) के लिए, sizeof(point)/sizeof(point[0]) चाल गतिशील आवंटित सरणी के लिए काम नहीं करती है, केवल स्टैक पर आवंटित एक सरणी है।

2

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

आपके प्रश्न का उत्तर The C Programming FAQ पर भी दिया गया है। प्रश्न 6.21।

+0

picky होने के लिए: यह सरणी के पहले तत्व के लिए एक सूचक है जो पारित हो जाता है। वही मूल्य, लेकिन अलग-अलग प्रकार। – alk

0

क्योंकि आकार() आपको सी में एक सरणी का आकार नहीं बताता है। यह कुछ पूरी तरह से अलग करता है।

sizeof C++ reference

+0

यदि आपने उदाहरण पर नजदीकी नजर डाली है, तो आप देखेंगे कि मैं सरणी में तत्वों की संख्या को सीधे प्राप्त करने के लिए आकार का उपयोग नहीं करता ... आकार मुझे बताएगा कि सरणी के लिए कितनी मेमोरी आरक्षित है ... और वास्तव में यह पता होना चाहिए कि तत्व के आकार को कब जाना जाता है, वहां कितने तत्व हैं। या क्या मैं कुछ न कुछ भूल रहा हूं? – dontWatchMyProfile

+0

मैं सही खड़ा हूँ। लेकिन जैसा ऊपर बताया गया है, पॉइंटर्स से सावधान रहें।वे आपको अपना आकार बताते हैं, न कि उस प्रकार का आकार जिसे आप इंगित कर रहे हैं। – PeterK

12

क्योंकि सरणी एक सूचक जब समारोह तर्क के रूप में पारित कर दिया करने के लिए decayed है, इसलिए sizeof आप 4 और 8 32- और 64-बिट प्लेटफार्मों के लिए क्रमशः देता है।

6

इसके अलावा, यह समझना महत्वपूर्ण है कि sizeof का मूल्यांकन संकलित समय पर किया गया है। चूंकि इस मामले में, test() में पारित होने के आधार पर विभिन्न आउटपुट की अपेक्षा करने का कोई अर्थ नहीं है। sizeof फ़ंक्शन संकलित होने पर गणना की गई थी।

2

क्योंकि सी, सी ++, और उद्देश्य-सी में, फ़ंक्शंस में वास्तव में सरणी पैरामीटर नहीं हो सकते हैं। उनके पास केवल पैरामीटर हो सकते हैं जो सरणी पैरामीटर की तरह दिखते हैं, लेकिन नहीं हैं। अपने उदाहरण में,

void test(int arr[]) 

संकलक देखता है "एक पैरामीटर है कि पूर्णांक की एक सरणी की तरह लग रहा है", और यह एक "int करने के लिए सूचक" के साथ उस पैरामीटर बदल देता है। तो समारोह है कि आप ने लिखा, बिल्कुल, एक सौ प्रतिशत है

void test (int* arr) 

के समान इसलिए, समारोह sizeof (आगमन) के अंदर आप एक "int करने के लिए सूचक" का आकार दे देंगे।

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