Char s [] और char * s के बीच क्या अंतर है?



5 Answers

सबसे पहले, कार्य तर्कों में, वे बिल्कुल बराबर हैं:

void foo(char *x);
void foo(char x[]); // exactly the same in all respects

अन्य संदर्भों में, char * एक पॉइंटर आवंटित करता है, जबकि char [] एक सरणी आवंटित करता है। स्ट्रिंग पहले मामले में कहां जाती है, आप पूछते हैं? संकलक सचमुच स्ट्रिंग अक्षर को पकड़ने के लिए एक स्थिर अज्ञात सरणी आवंटित करता है। इसलिए:

char *x = "Foo";
// is approximately equivalent to:
static const char __secret_anonymous_array[] = "Foo";
char *x = (char *) __secret_anonymous_array;

ध्यान दें कि आपको कभी भी इस अज्ञात सरणी की सामग्री को इस सूचक के माध्यम से संशोधित करने का प्रयास नहीं करना चाहिए; प्रभाव अपरिभाषित हैं (अक्सर एक दुर्घटना का अर्थ है):

x[1] = 'O'; // BAD. DON'T DO THIS.

सरणी सिंटैक्स का उपयोग सीधे इसे नई मेमोरी में आवंटित करता है। इस प्रकार संशोधन सुरक्षित है:

char x[] = "Foo";
x[1] = 'O'; // No problem.

हालांकि सरणी केवल तब तक जीवित रहती है जब तक कि आप इसे किसी फ़ंक्शन में नहीं करते हैं, इसलिए इस सरणी में एक पॉइंटर वापस न करें या रिसाव न करें - इसके बजाय strdup() या इसी तरह की प्रतिलिपि बनाएं। यदि सरणी वैश्विक दायरे में आवंटित की जाती है, बेशक, कोई समस्या नहीं है।

Question

सी में, कोई इस तरह की घोषणा में एक स्ट्रिंग अक्षर का उपयोग कर सकता है:

char s[] = "hello";

या इस तरह:

char *s = "hello";

तो अंतर क्या है? मैं जानना चाहता हूं कि संकलन अवधि के दौरान वास्तव में क्या होता है, दोनों संकलन और रन टाइम पर।




char s[] = "hello";

घोड़ों की एक सरणी घोषित करता है जो प्रारंभकर्ता (5 + 1 char एस) को पकड़ने के लिए काफी लंबा है और सरणी में दिए गए स्ट्रिंग के सदस्यों को प्रतिलिपि बनाकर सरणी को प्रारंभ करता है।

char *s = "hello";

एक या अधिक (इस मामले में अधिक) के लिए एक सूचक होने की घोषणा करता है और इसे सीधे एक निश्चित (केवल पढ़ने के लिए) स्थान पर इंगित करता है जिसमें शाब्दिक "hello"




char *str = "Hello";

उपर्युक्त सेट "हैलो" को इंगित करने के लिए स्ट्रेट को इंगित करता है जो प्रोग्राम की बाइनरी छवि में हार्ड-कोड किया गया है, जिसे केवल स्मृति में पढ़ने के रूप में चिह्नित किया गया है, इसका मतलब है कि इस स्ट्रिंग अक्षर में कोई भी बदलाव अवैध है और इससे विभाजन त्रुटियां फेंक जाएंगी।

char str[] = "Hello";

स्टैक पर नई आवंटित स्मृति को स्ट्रिंग की प्रतिलिपि बनाता है। इस प्रकार इसमें कोई बदलाव करने की अनुमति है और कानूनी है।

means str[0] = 'M';

स्ट्रिंग को "मेलो" में बदल देगा।

अधिक जानकारी के लिए, कृपया इसी तरह के प्रश्न से गुज़रें:

"Char * s" के साथ शुरू की गई स्ट्रिंग पर लिखते समय मुझे विभाजन खंड क्यों मिलता है लेकिन "char s []" नहीं?




एक अतिरिक्त के रूप में, इस बात पर विचार करें कि, केवल पढ़ने के उद्देश्यों के लिए दोनों का उपयोग समान है, आप [] या *(<var> + <index>) प्रारूप के साथ अनुक्रमणित करके एक char तक पहुंच सकते हैं:

printf("%c", x[1]);     //Prints r

तथा:

printf("%c", *(x + 1)); //Prints r

जाहिर है, अगर आप करने का प्रयास करते हैं

*(x + 1) = 'a';

आपको शायद सेगमेंटेशन फॉल्ट मिलेगा, क्योंकि आप केवल-पढ़ने वाली मेमोरी तक पहुंचने का प्रयास कर रहे हैं।




घोषणाओं को देखते हुए

char *s0 = "hello world";
char s1[] = "hello world";

निम्नलिखित काल्पनिक स्मृति मानचित्र मानें:

                    0x01  0x02  0x03  0x04
        0x00008000: 'h'   'e'   'l'   'l'
        0x00008004: 'o'   ' '   'w'   'o'
        0x00008008: 'r'   'l'   'd'   0x00
        ...
s0:     0x00010000: 0x00  0x00  0x80  0x00
s1:     0x00010004: 'h'   'e'   'l'   'l'
        0x00010008: 'o'   ' '   'w'   'o'
        0x0001000C: 'r'   'l'   'd'   0x00

स्ट्रिंग शाब्दिक "hello world" स्थैतिक भंडारण अवधि के साथ char (सी ++ में const char ) का एक 12-तत्व सरणी है, जिसका अर्थ यह है कि कार्यक्रम शुरू होने पर आवंटित किया जाता है और प्रोग्राम समाप्त होने तक आवंटित रहता है। एक स्ट्रिंग शाब्दिक सामग्री की सामग्री को संशोधित करने का प्रयास अपरिभाषित व्यवहार का आह्वान करता है।

रेखा

char *s0 = "hello world";

स्वत: भंडारण अवधि के साथ char को पॉइंटर के रूप में परिभाषित करता है (जिसका अर्थ है कि वेरिएबल एस 0 केवल उस दायरे के लिए मौजूद है जिसमें इसे घोषित किया गया है) और स्ट्रिंग 0x00008000 (इस उदाहरण में 0x00008000 ) के पते की प्रतिलिपि बनाता है। ध्यान दें कि चूंकि एक स्ट्रिंग s0 लिए s0 अंक हैं, इसलिए इसे किसी भी फ़ंक्शन के लिए तर्क के रूप में उपयोग नहीं किया जाना चाहिए जो इसे संशोधित करने का प्रयास करेगा (उदाहरण के लिए, strtok() , strcat() , strcpy() , आदि)।

रेखा

char s1[] = "hello world";

स्वत: भंडारण अवधि के साथ s1 को 12-तत्व सरणी (लम्बाई स्ट्रिंग अक्षर से लिया जाता है) के रूप में परिभाषित करता है और शाब्दिक की सामग्री को सरणी में प्रतिलिपि बनाता है। जैसा कि आप मेमोरी मैप से देख सकते हैं, हमारे पास "hello world" स्ट्रिंग की दो प्रतियां हैं; अंतर यह है कि आप s1 में निहित स्ट्रिंग को संशोधित कर सकते हैं।

s0 और s1 अधिकांश संदर्भों में अंतर-परिवर्तनीय हैं; यहां अपवाद हैं:

sizeof s0 == sizeof (char*)
sizeof s1 == 12

type of &s0 == char **
type of &s1 == char (*)[12] // pointer to a 12-element array of char

आप परिवर्तनीय एस 0 को एक अलग स्ट्रिंग अक्षर या किसी अन्य चर पर इंगित करने के लिए पुन: असाइन कर सकते हैं। आप एक अलग सरणी को इंगित करने के लिए चर s1 को पुन: असाइन नहीं कर सकते हैं।




के मामले में:

char *x = "fred";

एक्स एक lvalue - इसे असाइन किया जा सकता है। लेकिन इस मामले में:

char x[] = "fred";

एक्स एक लालसा नहीं है, यह एक रैल्यू है - आप इसे असाइन नहीं कर सकते हैं।






Related