इसे पूरी तरह से समझने के लिए, आपको निम्नलिखित अवधारणाओं को समझना चाहिए :
ऐरे पॉइंटर्स नहीं हैं!
सबसे पहले (और यह पर्याप्त प्रचार किया गया है), सरणियां संकेत नहीं हैं । इसके बजाय, अधिकांश उपयोगों में, वे अपने पहले तत्व के पते को 'क्षय' करते हैं, जिसे एक पॉइंटर को सौंपा जा सकता है:
int a[] = {1, 2, 3};
int *p = a; // p now points to a[0]
मुझे लगता है कि यह इस तरह से काम करता है ताकि सरणी की सामग्री को उन सभी को कॉपी किए बिना एक्सेस किया जा सके। यह केवल सरणी प्रकारों का एक व्यवहार है और इसका मतलब यह नहीं है कि वे समान हैं।
बहुआयामी सरणियाँ
बहुआयामी सरणियाँ एक तरह से मेमोरी को 'पार्टीशन' करने का एक तरीका है जिसे कंपाइलर / मशीन समझ और संचालित कर सकते हैं।
उदाहरण के लिए, int a[4][3][5]
= एक सरणी जिसमें पूर्णांक आकार की स्मृति के 4 * 3 * 5 (60) 'हिस्सा' होते हैं।
उपयोग करने पर लाभ int a[4][3][5]
बनाम सादे int b[60]
का है कि अब वे 'विभाजित' हो गए हैं (यदि आवश्यक हो तो अपने 'विखंडू के साथ काम करना आसान है), और कार्यक्रम अब बाध्य जाँच कर सकता है।
वास्तव में, int a[4][3][5]
संग्रहीत किया जाता है वास्तव में की तरह int b[60]
स्मृति में - केवल अंतर यह है कि कार्यक्रम अब इसे प्रबंधित करता है जैसे कि वे कुछ निश्चित आकार (विशेष रूप से, पांच के तीन समूहों के चार समूहों) की अलग-अलग इकाइयाँ हैं।
ध्यान रखें: दोनों int a[4][3][5]
और int b[60]
स्मृति में ही कर रहे हैं, और फर्क सिर्फ इतना है कि वे किस तरह आवेदन / संकलक द्वारा नियंत्रित कर रहे हैं
{
{1, 2, 3, 4, 5}
{6, 7, 8, 9, 10}
{11, 12, 13, 14, 15}
}
{
{16, 17, 18, 19, 20}
{21, 22, 23, 24, 25}
{26, 27, 28, 29, 30}
}
{
{31, 32, 33, 34, 35}
{36, 37, 38, 39, 40}
{41, 42, 43, 44, 45}
}
{
{46, 47, 48, 49, 50}
{51, 52, 53, 54, 55}
{56, 57, 58, 59, 60}
}
इससे, आप स्पष्ट रूप से देख सकते हैं कि प्रत्येक "विभाजन" केवल एक सरणी है जिसे प्रोग्राम ट्रैक करता है।
वाक्य - विन्यास
अब, सरणियाँ बिंदुओं से वाक्यात्मक रूप से भिन्न होती हैं । विशेष रूप से, इसका मतलब है कि संकलक / मशीन उन्हें अलग तरह से व्यवहार करेगी। यह बिना दिमाग के लग सकता है, लेकिन इस पर एक नज़र डालें:
int a[3][3];
printf("%p %p", a, a[0]);
उपरोक्त उदाहरण दो बार एक ही मेमोरी एड्रेस को प्रिंट करता है, जैसे:
0x7eb5a3b4 0x7eb5a3b4
हालाँकि, केवल एक पॉइंटर को सीधे ही सौंपा जा सकता है :
int *p1 = a[0]; // RIGHT !
int *p2 = a; // WRONG !
एक पॉइंटर को क्यों नहीं a
सौंपा जा सकता है लेकिन a[0]
हो सकता है?
यह, बस, बहुआयामी सरणियों का एक परिणाम है, और मैं समझाता हूँ क्यों:
' a
' के स्तर पर , हम अभी भी देखते हैं कि आगे देखने के लिए हमारे पास एक और 'आयाम' है। के स्तर पर 'a[0]
हालांकि, ' , हम पहले से ही शीर्ष आयाम में हैं, इसलिए जहां तक कार्यक्रम का संबंध है, हम सिर्फ एक सामान्य सरणी देख रहे हैं।
आप पूछ रहे होंगे:
अगर इसके लिए एक पॉइंटर बनाने के संबंध में यह सरणी बहुआयामी है तो यह क्यों मायने रखता है?
इस तरह से सोचना सबसे अच्छा है:
एक बहुआयामी सरणी से एक 'क्षय' केवल एक पता नहीं है, बल्कि विभाजन डेटा के साथ एक पता है (AKA) के यह अभी भी समझता है कि इसका अंतर्निहित डेटा अन्य सरणियों से बना है), जिसमें पहले आयाम से परे सरणी द्वारा निर्धारित सीमाएं शामिल हैं।
जब तक हम इसे निर्दिष्ट नहीं करते, यह 'पार्टीशन' तर्क एक पॉइंटर के भीतर मौजूद नहीं हो सकता है:
int a[4][5][95][8];
int (*p)[5][95][8];
p = a; // p = *a[0] // p = a+0
अन्यथा, सरणी के छंटाई गुणों का अर्थ खो जाता है।
चारों ओर कोष्ठक के उपयोग पर भी ध्यान दें *p
: int (*p)[5][95][8]
- यह निर्दिष्ट करना है कि हम इन सीमाओं के साथ एक संकेतक बना रहे हैं, न कि इन सीमाओं के साथ संकेत का एक सरणी:int *p[5][95][8]
निष्कर्ष
पिछली समीक्षा:
- यदि वे उपयोग किए गए संदर्भ में कोई अन्य उद्देश्य नहीं रखते हैं, तो पते का क्षय होता है
- बहुआयामी सरणियाँ केवल सरणियों के सारणी हैं - इसलिए, 'क्षय' पते "मैं उप आयाम" का भार वहन करेगा
- जब तक आप इसे नहीं देते, तब तक डायमेंशन डेटा एक पॉइंटर में मौजूद नहीं हो सकता ।
संक्षेप में: बहुआयामी सरणियों के पते का क्षय होता है जो उनकी सामग्री को समझने की क्षमता रखते हैं।