2009-06-19 15 views
6
char **Data[70]={NULL}; 

इसके लिए सही शब्दावली क्या है? यह और कैसे लिखा जा सकता है? यह स्मृति में कैसा दिखता है? मैं पॉइंटर्स पर कई ट्यूटोरियल पढ़ रहा हूं लेकिन मुझे इसे इस वाक्यविन्यास में नहीं दिख रहा है। किसी भी मदद की सराहना की है। धन्यवाद।पॉइंटर्स के पॉइंटर्स की एक सरणी कैसे काम करती है?

उत्तर

24

यह संरचना

char **Data[70]={NULL}; 

संकेत दिए गए चार करने के लिए करने के लिए 70 संकेत की एक सरणी है। कंपाइलर इस सरणी के लिए 70 * sizeof(char**) बाइट आवंटित करता है, जो 32-बिट पॉइंटर्स 280 बाइट मानते हैं।

यदि आप आंतरिक रूप से एक स्ट्रिंग के रूप में "पॉइंटर टू char" के बारे में सोचते हैं, जो सत्य नहीं है लेकिन यह काफी करीब है, तो यह तारों के लिए 70 पॉइंटर्स की एक सरणी है। कुछ ASCII आर्ट बनाने के लिए और बहाना है कि आप आवंटित और कुछ मूल्यों से जमा की है करने के लिए ....

Array of  One or more 
char **   char * 
+---------+  +---------+ 
| 0 | --> | ptr | --> "Hello, world" 
+---------+  +---------+ 
| 1 | 
+---------+  +---------+ 
| 2 | ----> | ptr2 | --> "Goodbye, cruel world" 
+---------+  +---------+ 
| 3 | 
+---------+   +---------+ 
| 4 | ------> | ptr3[0] | --> "Message 0" 
+---------+   +---------+ 
    ...    | ptr3[1] | --> "Message 1" 
+---------+   +---------+ 
| 69 |   | ptr3[2] | --> "Message 2" 
+---------+   +---------+ 

आप (त्रुटि जाँच malloc वापसी मूल्यों को छोड़ दिया) इस तरह के कोड के साथ ऊपर कर सकता है:

char **Data[70]={NULL}; 
char **ptr, **ptr2, **ptr3; 

ptr = (char **) malloc(sizeof(char *)); 
*ptr = "Hello, world"; 
Data[0] = ptr; 

ptr2 = (char **) malloc(sizeof(char *)); 
*ptr2 = "Goodbye, cruel world"; 
Data[2] = ptr2; 

ptr3 = (char **) malloc(10 * sizeof(char *)); 
Data[4] = ptr3; 

ptr3[0] = "Message 0"; 
ptr3[1] = "Message 1"; 
... 
ptr3[9] = "Message 9"; 

printf("%s\n", *Data[0]); 
printf("%s\n", Data[2][0]); 
printf("%s\n", Data[4][0]); 
printf("%s\n", Data[4][1]); 
     ... 
printf("%s\n", Data[4][9]); 

इस बारे में सोचें: सरणी में प्रत्येक प्रविष्टि char ** है। प्रत्येक प्रविष्टि स्मृति में एक मनमाना स्थान को इंगित कर सकती है, कहा गया स्थान char * है और इस प्रकार एक शून्य-समाप्त वर्ण सरणी उर्फ ​​"स्ट्रिंग" को इंगित करने में सक्षम है।

नोट ध्यान से इस और क्या बीच भेद जब आप एक 2 डी सरणी का आवंटन आपको मिलेगा:

char *Data2[10][70]={NULL}; 

Data2 के आवंटन ऊपर आप char * संकेत के एक 2-आयामी सरणी देता है, ने कहा कि 2-डी सरणी जा रहा है स्मृति के एक टुकड़े में आवंटित (10 * 70 * sizeof(char*) बाइट्स, या 32-बिट पॉइंटर्स के साथ 2800 बाइट्स)। आपके पास char ** पॉइंटर्स को char ** पॉइंटर्स की एकल-आयामी सरणी के साथ स्मृति में मनमानी स्थानों पर असाइन करने की क्षमता नहीं है।

भी ध्यान रखें कि संकलक निम्नलिखित सरणी संदर्भ के लिए अलग-अलग कोड उत्पन्न होगा (Data की घोषणाओं और Data2 ऊपर दिए गए):

Data[0][0] 
Data2[0][0] 

यहाँ एक और तरीका यह के बारे में सोचना है: कल्पना कीजिए कि आप कई है तारों के पॉइंटर्स के सरणी:

char *table0[] = { "Tree", "Bench", "Stream" }; 
char *table1[] = { "Cow", "Dog", "Cat" }; 
char *table2[] = { "Banana", "Carrot", "Broccoli" }; 
char **Data[3]; 

Data[0] = table0; 
Data[1] = table1; 
Data[2] = table2; 

आपके पास "पॉइंटर टू चार्" के पॉइंटर्स की एक सरणी है। यदि अब आप data[1][1] के मान को प्रिंट करते हैं, तो इस बारे में सोचें: आपको table1 सरणी में एक सूचक प्राप्त करता है। फिर मान table1[1]"Dog" के बराबर है।

+1

आपके महान उत्तर को इस पालतू-पीवी-उत्तर से लापरवाही से जोड़ा गया है: http://stackoverflow.com/questions/423823/whats-your-favorite-programmer-ignorance-pet-peeve/484900#484900। चीयर्स :) –

+0

इस तरह के एक अच्छे जवाब लिखने के लिए समय लेने के लिए धन्यवाद। यह बहुत साफ हो जाता है। जहां तक ​​आपका पहला आरेख, आप कैसे जानते हैं कि सूचक एक पॉइंटर (जैसे पीआरटी 2) या पॉइंटर्स की एक सरणी को इंगित कर रहा है, जैसे कि ptr3 [0-2] क्या यह आरेख में दोनों हो सकता है? उदाहरण के लिए, आपका दूसरा चित्र सुसंगत है। धन्यवाद। –

+0

यह जानने का कोई तरीका नहीं है कि वास्तव में, एक char ** सूचक बिंदु क्या है। यह किसी भी आकार के स्मृति क्षेत्र को इंगित कर सकता है। कोड को देखे बिना इसे सौंपा गया है, जानने का कोई तरीका नहीं है। – Eddie

0

यह प्रभावी रूप से पॉइंटर्स को पॉइंटर के लिए सूचक है। हालांकि, चूंकि "पॉइंटर" स्मृति में एक स्थान के अलावा कुछ भी नहीं है, इसलिए वास्तव में यह करने के अलावा char * डेटा [70] करने में ऐसा करने में बहुत अधिक उपयोग नहीं है, यह स्पष्ट करने के अलावा कि प्रत्येक char * एक अन्य चार के लिए सूचक है *, चार के लिए एक सूचक के बजाय।

1

यह बहुत स्पष्ट नहीं है:

char **Data[70]={NULL}; 

लेकिन एक विकल्प के घोषणा के साथ, जैसे:

char* Data[2][3] = { 
    {"Nick", "Tom", "Helen"}, 
    {"one", "two", "three"} 
}; 

हम आसानी से देख सकते हैं कि यह तार के एक 2 आयामी सरणी है।

संपादित करें: मैंने डेटा [2] [3] का उपयोग यह दिखाने के लिए किया कि यह 2 डी सरणी है। मैंने प्रदर्शन के लिए 2 & 3 जैसे आयामों के लिए निश्चित आकार का उपयोग किया। बेशक हमारे पास कर सकते हैं:

char* Data[][3]={ 
    {"Nick", "Tom", "Helen"}, 
    {"one", "two", "three"}, 
    // ... 
}; 

या char** Data[]

ठीक है, यहाँ है कि मैं क्या 2-डी सरणी मतलब है:

char** Data[2]={0}; 

void test() 
{ 
    char* d1[] = {"1", "2"}; 
    char* d2[] = {"10", "20", "30"}; 
    Data[0] = d1; 
    Data[1] = d2; 

    printf("%s\n", Data[0][0]); 
    printf("%s\n", Data[0][1]); 
    printf("%s\n", Data[1][0]); 
    printf("%s\n", Data[1][1]); 
    printf("%s\n", Data[1][2]); 
} 
+1

यह वास्तव में तारों की 2-डी सरणी नहीं है। आपकी घोषणा आपको उसके मुकाबले कुछ अलग करती है। – Eddie

+0

तो यह पॉइंटर्स की 2 डी सरणी नहीं है? –

+0

क्या अंतर है? –

2

यह एक के लिए एक व्यावहारिक उपयोग के बारे में सोचना थोड़ा मुश्किल है चार की सरणी **। विशेष रूप से 70 तत्वों के साथ एक।

हालांकि, मान लीजिए कि मैं 70 कार्यक्रम चलाने जा रहा हूं। जैसा कि आप शायद जानते हैं, कार्यक्रम तर्क आमतौर पर char** argv पैरामीटर main() (या char*[] argv) के रूप में पारित किए जाते हैं, जो फ़ंक्शन हस्ताक्षर में एक ही चीज़ है)। तो अगर मैं उन सभी कार्यक्रमों के लिए argv पॉइंटर्स को स्टोर करना चाहता था, तो मैं Data की तरह सरणी का उपयोग करता था। जाहिर है, मुझे वास्तविक तारों और Argv arrays पर कब्जा करने के लिए कहीं और स्मृति की आवश्यकता होगी, लेकिन यह एक शुरुआत है।

{NULL} के साथ एक सरणी शुरू करने से इसके सभी तत्व न्यूल पर सेट हो जाते हैं। यह एक उपयोगी शॉर्टेंड है: आप {firstelement, secondelement, ...} के साथ एक सरणी प्रारंभ कर सकते हैं, लेकिन यदि आप पर्याप्त शर्तों को प्रदान नहीं करते हैं, तो बाकी सभी को 0

किसी भी अन्य बिंदुओं की तरह, {NULL} के साथ प्रारंभ किया गया है, स्मृति में यह कैसा दिखता है वह 70 न्यूल पॉइंटर्स एक पंक्ति में बैठा है। char** और किसी अन्य ऑब्जेक्ट पॉइंटर के बीच स्मृति में आमतौर पर कोई अंतर नहीं होता है। मुझे लगता है कि एक अजीब कार्यान्वयन लिखना कानूनी है जिसमें एक अंतर है, लेकिन अपनी सांस को एक में आने का इंतजार न करें।

तो, एक पंक्ति में 70 शून्य char** और एक पंक्ति में 70 शून्य char* के बीच का अंतर क्या सूचक के दूसरे छोर पर होगा, अगर वे शून्य नहीं थे। char** के दूसरे छोर पर एक char के लिए एक सूचक है। char* के दूसरे छोर पर एक char है। या तो पॉइंटर, या चार, एक सरणी में पहला हो सकता है, इस पर निर्भर करता है कि इसका उपयोग कैसे किया जा रहा है।

1

आपको जो मिला है वह 70 पॉइंटर्स की एक सरणी है, जिनमें से प्रत्येक एक अन्य पॉइंटर को इंगित करता है, उनमें से प्रत्येक पॉइंटर्स चार को इंगित करता है। एक दिलचस्प नोट पर, सरणी स्वयं पॉइंटर्स हैं इसलिए आपके पास पॉइंटर्स के तीन स्तर हैं।

+0

Arrays पॉइंटर्स नहीं हैं। –

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