किसी सरणी पैरामीटर का आकार मुख्य के समान क्यों नहीं है?


104

किसी सरणी के आकार को मुख्य के रूप में पैरामीटर के समान क्यों नहीं भेजा जाता है?

#include <stdio.h>

void PrintSize(int p_someArray[10]);

int main () {
    int myArray[10];
    printf("%d\n", sizeof(myArray)); /* As expected, 40 */
    PrintSize(myArray);/* Prints 4, not 40 */
}

void PrintSize(int p_someArray[10]){
    printf("%d\n", sizeof(p_someArray));
}

जवाबों:


103

जब आप इसे किसी फ़ंक्शन में पास करते हैं, तो एक सरणी-प्रकार को स्पष्ट रूप से सूचक प्रकार में बदल दिया जाता है।

इसलिए,

void PrintSize(int p_someArray[10]) {
    printf("%zu\n", sizeof(p_someArray));
}

तथा

void PrintSize(int *p_someArray) {
    printf("%zu\n", sizeof(p_someArray));
}

समतुल्य हैं। तो आपको जो मिलता है उसका मूल्य हैsizeof(int*)


1
C ++ में आप फंक्शन के संदर्भ में एरे पास कर सकते हैं लेकिन आप ऐसा नहीं कर सकते। C.
प्रसून सौरव

13
आपको सरणी के आकार को एक अलग पैरामीटर के रूप में पास करना होगा। फिर सरणी का आकार आकार का होगा (* p_someArray) * लंबाई
अरेक टेनइक

13
माइनर नाइट: sizeofऑपरेटर एक प्रकार का ऑब्जेक्ट लौटाता है size_t, इसलिए आपको इसे %zu(C99) के साथ प्रिंट करना चाहिए , या intयदि आप %dअपनी printfकॉल में ऊपर की तरह उपयोग करते हैं , तो इसे डाल दें ।
आलोक सिंघल

4
आलोक का कथन सही है। Printf (..) में गलत प्रारूप विनिर्देशक का उपयोग करना UB है।
प्रसून सौरव

1
@ क्रिस_45: सी का कोई संदर्भ नहीं है, लेकिन सी में आप एक सरणी को सूचक द्वारा पूरे सरणी में पास कर सकते हैं जैसे void PrintSize(int (*p_someArray)[10]):। समारोह के अंदर आप भिन्नता ऑपरेटर का उपयोग करके सरणी का उपयोग कर सकते *: sizeof(*p_someArray)। यह C ++ में संदर्भों का उपयोग करने के समान प्रभाव होगा।
एनटी

18

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


16

जैसा कि दूसरों ने कहा है, फ़ंक्शन पैरामीटर के रूप में उपयोग किए जाने पर सरणियों को उनके पहले तत्व को इंगित करने के लिए क्षय होता है। यह भी ध्यान देने योग्य है कि साइज़ोफ़ अभिव्यक्ति का मूल्यांकन नहीं करता है और अभिव्यक्ति के साथ उपयोग किए जाने पर कोष्ठक की आवश्यकता नहीं होती है, इसलिए आपके पैरामीटर का वास्तव में उपयोग नहीं किया जा रहा है, इसलिए आप वैल्यू के बजाय साइज़ोफ़ को टाइप के साथ लिख सकते हैं।

#include <stdio.h>

void PrintSize1 ( int someArray[][10] );
void PrintSize2 ( int someArray[10] );

int main ()
{
    int myArray[10];
    printf ( "%d\n", sizeof myArray ); /* as expected 40 */
    printf ( "%d\n", sizeof ( int[10] ) ); /* requires parens */
    PrintSize1 ( 0 ); /* prints 40, does not evaluate 0[0] */
    PrintSize2 ( 0 ); /* prints 40, someArray unused */
}

void PrintSize1 ( int someArray[][10] )
{
    printf ( "%d\n", sizeof someArray[0] );
}

void PrintSize2 ( int someArray[10] )
{
    printf ( "%d\n", sizeof ( int[10] ) );
}

12

तो, आपको दूसरे पैरामीटर के रूप में सरणी के लेन को पास करना होगा। जब आप कोड लिख रहे होते हैं, जिसमें आप दोनों निरंतर आकार की एक सरणी की घोषणा करते हैं, और बाद में उस सरणी को किसी फ़ंक्शन में पास करते हैं, तो यह एक दर्द है कि आपके कोड में कई स्थानों पर सरणी-लंबाई निरंतर दिखाने के लिए ...

बचाव के लिए कश्मीर और आर:

#define N_ELEMENTS(array) (sizeof(array)/sizeof((array)[0])) 

तो अब आप कर सकते हैं जैसे:

int a[10];
...
myfunction(a, N_ELEMENTS(a));

क्या होगा यदि सरणी का आकार कोडिंग समय पर उपलब्ध नहीं है, लेकिन केवल रन समय पर उपलब्ध है? क्या इसके आकार को हार्ड-कोडिंग के बिना सरणी के आकार की गणना करने का कोई अन्य तरीका है?
weefwefwqg3

दिखाया गया तरीका केवल तभी काम करता है, जब सरणी की घोषणा "देखने में" हो। अन्य सभी मामलों के लिए, आपको मैन्युअल रूप से सरणी-लंबाई को पास करना होगा।
एससी मैडसेन

5

क्योंकि एरियर्स बिंदुओं में क्षय हो जाता है जब वे मापदंडों के रूप में पारित हो जाते हैं। यह है कि C कैसे काम करता है, हालाँकि आप संदर्भ में C ++ में "सरणियाँ" पास कर सकते हैं और इस समस्या को दूर कर सकते हैं। ध्यान दें कि आप इस फ़ंक्शन के विभिन्न आकारों के सरणियाँ पास कर सकते हैं:

 // 10 is superfluous here! You can pass an array of different size!
void PrintSize(int p_someArray[10]);

5

आपके द्वारा पाया गया व्यवहार वास्तव में C भाषा में एक बड़ा मस्सा है। जब भी आप एक फ़ंक्शन की घोषणा करते हैं जो एक सरणी पैरामीटर लेता है, तो कंपाइलर आपको अनदेखा करता है और पैरामीटर को पॉइंटर में बदलता है। इसलिए ये घोषणाएं पहले वाले की तरह व्यवहार करती हैं:

void func(int *a)
void func(int a[])
void func(int a
typedef int array_plz[5];
void func(array_plz a)

होगा सभी चार मामलों में int के लिए एक सूचक होगा। यदि आप एक एरेस को फंक करने के लिए पास करते हैं, तो यह तुरंत एक पॉइंटर में अपने पहले तत्व को क्षय करेगा। (64-बिट सिस्टम पर, एक 64-बिट पॉइंटर 32-बिट इंट के रूप में दोगुना है, इसलिए आपका साइज़ोफ़ रिटर्न 2.)

इस नियम का एकमात्र उद्देश्य ऐतिहासिक संकलक के साथ पीछे की संगतता बनाए रखना है जो फ़ंक्शन तर्कों के रूप में समग्र मूल्यों को पारित करने का समर्थन नहीं करता है।

इसका मतलब यह नहीं है कि किसी फ़ंक्शन के लिए एक सरणी पास करना असंभव है। आप इस मस्से को एक संरचना में एम्बेड करके प्राप्त कर सकते हैं (यह मूल रूप से C ++ 11 के std :: array का उद्देश्य है):

struct array_rly {
int a[5];
};
void func(struct array_rly a)
{
printf("%zd\n", sizeof(a.a)/sizeof(a.a[0]));  /* prints 5 */
}

या सरणी के लिए एक पॉइंटर पास करके:

void func(const int (*a)[5])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0]));  /* prints 5 */
}

यदि सरणी आकार एक संकलन-समय स्थिर नहीं है, तो आप पॉइंटर-टू-सरणी तकनीक का उपयोग C99 चर-लम्बाई के साथ कर सकते हैं:

void func(int n, const int (*a)[n])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0]));  /* prints n */
}

4

सी ++ में आप इस उद्देश्य के लिए संदर्भ द्वारा एक सरणी पास कर सकते हैं:

void foo(int (&array)[10])
{
    std::cout << sizeof(array) << "\n";
}

1
यह C प्रश्न के साथ कैसे मदद करेगा?
ALK

3

सी भाषा में, किसी अज्ञात सरणी के आकार को निर्धारित करने के लिए कोई विधि नहीं है, इसलिए मात्रा को पहले तत्व के लिए एक संकेतक के साथ-साथ पारित करने की आवश्यकता है।


2
सामान्य तौर पर, आपको हमेशा किसी फ़ंक्शन के साथ सरणी के आकार (तत्वों की संख्या) को पास करना चाहिए, जब तक कि आपके पास इसके आकार को निर्धारित करने के कुछ अन्य साधन न हों (जैसे, char[]स्ट्रिंग सरणियों के अंत में एक अशक्त वर्ण टर्मिनेटर )।
डेविड आर ट्रिब्बल

कृपया " अज्ञात सरणी " क्या है?
ALK

3

आप फ़ंक्शन के लिए सरणियाँ पास नहीं कर सकते।

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

#include <stdio.h>

void PrintSize(int (*p_anArray)[10]);

int main(void) {
    int myArray[10];
    printf("%d\n", sizeof(myArray)); /* as expected 40 */
    PrintSize(&myArray);/* prints 40 */
}

void PrintSize(int (*p_anArray)[10]){
    printf("%d\n", (int) sizeof(*p_anArray));
}

0

व्यवहार डिजाइन द्वारा है।

फंक्शन पैरामीटर डिक्लेरेशन में समान सिंटैक्स का मतलब स्थानीय चर परिभाषा की तुलना में पूरी तरह से अलग है।

इसका कारण अन्य उत्तरों में वर्णित है।


0

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

fun (int [a]), fun (int * a) के समान है;

इसलिए जब आप सरणी का आकार प्रिंट करते हैं तो यह पहले तत्व के आकार को प्रिंट करेगा।


सी में " संदर्भ द्वारा कॉल " नहीं है।
ALK

" जब आप सरणी का आकार प्रिंट करेंगे तो यह पहले तत्व के आकार को प्रिंट करेगा। " नहीं, यह एक पॉइंटर के आकार को प्रिंट करता है।
एल्क

-1

'C' प्रोग्रामिंग में डाउनसाइज़ 'sizeof ()' ऑपरेटर है और वह बाइट्स में ऑब्जेक्ट का साइज़ लौटाता है। 'sizeof ()' ऑपरेटर का लेग-लेफ्ट वैल्यू टाइप (पूर्णांक, फ्लोट नंबर, स्ट्रक्चर, एरे) होना चाहिए )। यदि आप बाइट्स में किसी सरणी के आकार को जानना चाहते हैं, तो आप इसे बहुत ही सरल तरीके से कर सकते हैं। बस 'साइज़ोफ़ ()' ऑपरेटर का उपयोग करें और उनके तर्क के लिए ऐरे नाम का उपयोग करें। उदाहरण के लिए:

#include <stdio.h>

main(){

 int n[10];
 printf("Size of n is: %d \n", sizeof(n)); 

}

32 बिट सिस्टम पर आउटपुट होगा: n का आकार है: 40 सिस्टम पर 40 इनसेबर्गर इनचार्ज 4bytes.On 64x है यह 8bytes है। इस मामले में हमारे पास एक सरणी में 10 पूर्णांक घोषित किए गए हैं। इसके परिणामस्वरूप '10 '/ sizeof (है) पूर्णांक) '।

कुछ सुझाव:

अगर हमारे पास एक ऐसा ऐलान है, जैसे 'int n [] = {1, 2, 3, ... 155 ..};'। इसलिए हम जानना चाहते हैं कि इस सरणी में कितने तत्व संग्रहीत हैं। इस alghorithm का उपयोग करें:

sizeof (name_of_the_array) / sizeof (array_type)

कोड: #include

मुख्य(){

int n[] = { 1, 2, 3, 44, 6, 7 };
printf("Number of elements: %d \n", sizeof(n) / sizeof(int));
return 0;

}


2
StackOverflow में आपका स्वागत है और उत्तर लिखने के लिए धन्यवाद। दुर्भाग्य से, यह प्रश्न को संबोधित नहीं करता है, जो विशेष रूप से sizeof(n)एक स्थानीय चर के लिए और sizeof(arg)किसी फ़ंक्शन के तर्क के बीच अंतर के बारे में है , भले ही दोनों प्रकार के प्रतीत होते हैं int[10]
माइक्रो वायरस

-3

Arrays केवल शिथिल आकार के होते हैं। अधिकांश भाग के लिए, एक सरणी स्मृति के लिए एक संकेतक है। आपकी घोषणा में आकार केवल संकलक को बताता है कि सरणी के लिए कितनी मेमोरी आवंटित करना है - यह प्रकार से जुड़ा नहीं है, इसलिए आकार () में कुछ भी नहीं है।


3
क्षमा करें, यह उत्तर भ्रामक है। न तो सरणियाँ "शिथिल आकार" हैं, और न ही वे "स्मृति के संकेत" हैं। एरे का आकार बहुत सटीक होता है, और जिन स्थानों पर एक सरणी नाम अपने पहले तत्व के लिए पॉइंटर के लिए खड़ा होता है, वह ठीक सी मानक द्वारा निर्दिष्ट होता है।
जेन्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.