स्ट्रिंग स्ट्रिंग के साथ आरंभिक "char * s" लिखने पर मुझे एक विभाजन दोष क्यों मिलता है, लेकिन "char s]" नहीं?


288

निम्न कोड 2 लाइन पर seg गलती प्राप्त करता है:

char *str = "string";
str[0] = 'z';  // could be also written as *str = 'z'
printf("%s\n", str);

जबकि यह पूरी तरह से अच्छी तरह से काम करता है:

char str[] = "string";
str[0] = 'z';
printf("%s\n", str);

MSVC और GCC के साथ परीक्षण किया गया।


1
इसका मजाकिया - लेकिन यह वास्तव में संकलित करता है और एक दृश्य स्टूडियो डेवलपर कमांड प्रॉम्प्ट पर विंडोज़ कंपाइलर (सीएल) का उपयोग करते समय पूरी तरह से चलता है। कुछ पलों के लिए मुझे उलझन में डाल दिया ...
डेविड रेफेली

जवाबों:


242

C FAQ देखें, प्रश्न 1.32

प्रश्न : इन आरोपणों के बीच क्या अंतर है?
char a[] = "string literal";
char *p = "string literal";
यदि मैं एक नया मान असाइन करने का प्रयास करता हूं तो मेरा प्रोग्राम क्रैश हो जाता है p[i]

: एक स्ट्रिंग शाब्दिक (सी स्रोत में एक डबल-उद्धृत स्ट्रिंग के लिए औपचारिक शब्द) दो अलग-अलग तरीकों से उपयोग किया जा सकता है:

  1. वर्ण की एक सरणी के लिए इनिशलाइज़र के रूप में, की घोषणा में char a[], यह उस ऐरे में वर्णों के प्रारंभिक मूल्यों को निर्दिष्ट करता है (और, यदि आवश्यक हो, तो इसका आकार)।
  2. कहीं भी, यह वर्णों के एक अनाम, स्थिर सरणी में बदल जाता है, और यह अनाम सरणी केवल-पढ़ने के लिए स्मृति में संग्रहीत किया जा सकता है, और इसलिए जरूरी नहीं कि इसे संशोधित किया जा सके। एक अभिव्यक्ति के संदर्भ में, सरणी को एक बार एक पॉइंटर में बदल दिया जाता है, हमेशा की तरह (खंड 6 देखें), इसलिए दूसरी घोषणा पी को प्रारंभिक नाम के पहले तत्व की ओर इंगित करती है।

कुछ कंपाइलरों में एक स्विच होता है जो नियंत्रित करता है कि स्ट्रिंग शाब्दिक हैं या नहीं (पुराने कोड को संकलित करने के लिए), और कुछ के पास विकल्प हो सकते हैं कि स्ट्रिंग शाब्दिकों को औपचारिक रूप से कांस्ट चार्ज (बेहतर त्रुटि पकड़ने के लिए) के सरणियों के रूप में माना जाए।


7
अन्य बिंदुओं के युगल: (1) सेगफॉल्ट वर्णित के रूप में होता है, लेकिन इसकी घटना रन पर्यावरण का एक कार्य है; यदि समान कोड एक एम्बेडेड सिस्टम में था, तो लिखने का कोई प्रभाव नहीं हो सकता है, या यह वास्तव में s को z में बदल सकता है। (२) क्योंकि स्ट्रिंग शाब्दिक गैर-लेखन हैं, संकलक एक ही स्थान पर "स्ट्रिंग" के दो उदाहरण लगाकर अंतरिक्ष को बचा सकता है; या, यदि कोड में कहीं और आपके पास "एक और स्ट्रिंग" है, तो मेमोरी का एक हिस्सा दोनों शाब्दिकों का समर्थन कर सकता है। स्पष्ट रूप से, यदि कोड को उन बाइट्स को बदलने की अनुमति दी गई थी, तो अजीब और मुश्किल कीड़े हो सकते हैं।
greggo

1
@ समूहगो: अच्छी बात है। MMU के साथ सिस्टम पर ऐसा करने का एक तरीका यह भी है कि mprotectकेवल पढ़ने के लिए सुरक्षा का उपयोग करके ( यहां देखें )।

तो चार * पी = "ब्ला" वास्तव में एक अस्थायी सरणी बनाता है? अजीब।
राहुल त्यागी 13

1
और C ++ में लिखने के 2 साल बाद ... TIL
zeboidlund

@rahultyagi क्या मतलब है आपका?
सूरज जैन

105

आम तौर पर, स्ट्रिंग शाब्दिक को केवल-पढ़ने के लिए मेमोरी में संग्रहीत किया जाता है जब प्रोग्राम चलाया जाता है। यह आपको गलती से एक स्ट्रिंग निरंतर बदलने से रोकने के लिए है। आपके पहले उदाहरण में, "string"रीड-ओनली मेमोरी में स्टोर किया *strगया है और पहले कैरेक्टर की ओर इशारा करता है। जब आप पहले वर्ण को बदलने की कोशिश करते हैं तो सेगफॉल्ट होता है 'z'

दूसरे उदाहरण में, स्ट्रिंग "string"को कंपाइलर द्वारा उसके रीड-ओनली होम से ऐरे में कॉपी किया जाता है str[]। फिर पहले चरित्र को बदलने की अनुमति है। आप प्रत्येक के पते को प्रिंट करके इसकी जांच कर सकते हैं:

printf("%p", str);

इसके अलावा, strदूसरे उदाहरण के आकार को प्रिंट करना आपको दिखाएगा कि संकलक ने इसके लिए 7 बाइट आवंटित किए हैं:

printf("%d", sizeof(str));

13
जब भी प्रिंटफ़ पर "% p" का उपयोग किया जाता है, तो आपको पॉइंटर को * शून्य में प्रिंट करने के लिए डालना चाहिए (जैसे "% p", (void *) str); Printf के साथ size_t प्रिंट करते समय, आपको नवीनतम C मानक (C99) का उपयोग करते हुए "% zu" का उपयोग करना चाहिए।
क्रिस यंग

4
इसके अलावा, आकार के साथ कोष्ठक केवल तब आवश्यक होते हैं जब एक प्रकार का आकार लेते हैं (तर्क तब एक डाली की तरह दिखता है)। याद रखें कि sizeof एक ऑपरेटर है, एक फ़ंक्शन नहीं है।
खोलना


34

इनमें से अधिकांश उत्तर सही हैं, लेकिन केवल थोड़ा और स्पष्टता जोड़ने के लिए ...

"केवल पढ़ने के लिए मेमोरी" जिसका लोग उल्लेख कर रहे हैं वह ASM शब्दों में टेक्स्ट सेगमेंट है। यह स्मृति में एक ही जगह है जहां निर्देश लोड किए जाते हैं। यह सुरक्षा जैसे स्पष्ट कारणों के लिए केवल पढ़ने के लिए है। जब आप एक स्ट्रिंग के लिए आरंभिक चार * बनाते हैं, तो स्ट्रिंग डेटा को टेक्स्ट सेगमेंट में संकलित किया जाता है और प्रोग्राम टेक्स्ट सेगमेंट में इंगित करने के लिए पॉइंटर को इनिशियलाइज़ करता है। इसलिए अगर आप इसे बदलने की कोशिश करते हैं, तो काबूम। Segfault।

जब एक सरणी के रूप में लिखा जाता है, तो कंपाइलर आरंभिक स्ट्रिंग डेटा को डेटा सेगमेंट में रखता है, जो कि वही स्थान है जो आपके वैश्विक चर और ऐसे लाइव हैं। यह स्मृति परिवर्तनशील है, क्योंकि डेटा खंड में कोई निर्देश नहीं हैं। इस बार जब कंपाइलर कैरेक्टर ऐरे (जो अभी भी एक चार * है) को इनिशियलाइज़ करता है, यह टेक्स्ट सेगमेंट के बजाय डेटा सेगमेंट में इंगित होता है, जिसे आप रन-टाइम पर सुरक्षित रूप से बदल सकते हैं।


लेकिन क्या यह सच नहीं है कि "रीड-ओनली मेमोरी" को संशोधित करने की अनुमति देने वाले कार्यान्वयन हो सकते हैं?
पचेरियर

जब एक सरणी के रूप में लिखा जाता है, तो कंपाइलर आरंभिक स्ट्रिंग डेटा को डेटा खंड में रखता है यदि वे स्थिर या वैश्विक हैं। अन्यथा (जैसे एक सामान्य स्वचालित सरणी के लिए) यह स्टैक पर जगह देता है, फ़ंक्शन मुख्य के स्टैक फ्रेम में। सही बात?
SE

27

स्ट्रिंग लिखते समय मुझे एक विभाजन दोष क्यों मिलता है?

C99 N1256 ड्राफ्ट

चरित्र स्ट्रिंग शाब्दिक के दो अलग-अलग उपयोग हैं:

  1. प्रारंभिक char[]:

    char c[] = "abc";      

    यह "अधिक जादू" है, और 6.7.8 / 14 "प्रारंभिककरण" में वर्णित है:

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

    तो यह सिर्फ एक शॉर्टकट है:

    char c[] = {'a', 'b', 'c', '\0'};

    किसी भी अन्य नियमित सरणी की तरह, cसंशोधित किया जा सकता है।

  2. हर जगह: यह एक उत्पन्न करता है:

    इसलिए जब आप लिखते हैं:

    char *c = "abc";

    यह इसके समान है:

    /* __unnamed is magic because modifying it gives UB. */
    static char __unnamed[] = "abc";
    char *c = __unnamed;

    नोट से निहित कलाकारों char[]के लिए char *है, जो हमेशा कानूनी है।

    फिर यदि आप संशोधित करते हैं c[0], तो आप संशोधित भी करते हैं __unnamed, जो कि यूबी है।

    यह 6.4.5 "स्ट्रिंग शाब्दिक" पर प्रलेखित है:

    5 अनुवाद चरण 7 में, एक बाइट या मूल्य शून्य का कोड प्रत्येक मल्टीबीट चरित्र अनुक्रम में जोड़ा जाता है जो एक स्ट्रिंग शाब्दिक या शाब्दिक परिणाम होता है। मल्टीबाइट कैरेक्टर सीक्वेंस का इस्तेमाल तब स्टैटिक स्टोरेज की अवधि और लंबाई को व्यवस्थित करने के लिए किया जाता है। चरित्र स्ट्रिंग शाब्दिकों के लिए, सरणी तत्वों में चार वर्ण होते हैं, और इन्हें मल्टीबाइट वर्ण अनुक्रम के अलग-अलग बाइट्स के साथ आरंभ किया जाता है ...]

    6 यह स्पष्ट नहीं है कि क्या ये सरणियाँ अलग-अलग हैं बशर्ते उनके तत्वों में उचित मूल्य हों। यदि प्रोग्राम ऐसे सरणी को संशोधित करने का प्रयास करता है, तो व्यवहार अपरिभाषित है।

6.7.8 / 32 "प्रारंभिक" एक प्रत्यक्ष उदाहरण देता है:

उदाहरण 8: घोषणा

char s[] = "abc", t[3] = "abc";

"सादे" वर्ण सरणी वस्तुओं को परिभाषित करता है sऔर tजिनके तत्व वर्ण स्ट्रिंग शाब्दिक के साथ आरंभिक होते हैं।

यह घोषणा समान है

char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };

सरणियों की सामग्री परिवर्तनीय हैं। दूसरी ओर, घोषणा

char *p = "abc";

pप्रकार "पॉइंटर टू चार" के साथ परिभाषित करता है और इसे एक ऑब्जेक्ट के साथ इंगित करने के लिए टाइप करता है "वर्ण का प्रकार" लंबाई 4 के साथ जिसका तत्व एक चरित्र स्ट्रिंग शाब्दिक के साथ आरम्भ किया गया है। यदि pसरणी की सामग्री को संशोधित करने के लिए उपयोग करने का प्रयास किया जाता है , तो व्यवहार अपरिभाषित है।

जीसीसी 4.8 x86-64 ईएलएफ कार्यान्वयन

कार्यक्रम:

#include <stdio.h>

int main(void) {
    char *s = "abc";
    printf("%s\n", s);
    return 0;
}

संकलन और विघटित:

gcc -ggdb -std=c99 -c main.c
objdump -Sr main.o

आउटपुट में शामिल हैं:

 char *s = "abc";
8:  48 c7 45 f8 00 00 00    movq   $0x0,-0x8(%rbp)
f:  00 
        c: R_X86_64_32S .rodata

निष्कर्ष: GCC char*इसे .rodataअनुभाग में संग्रहीत करता है , अंदर नहीं .text

यदि हम ऐसा ही करते हैं char[]:

 char s[] = "abc";

हमने प्राप्त किया:

17:   c7 45 f0 61 62 63 00    movl   $0x636261,-0x10(%rbp)

तो यह स्टैक में संग्रहीत हो जाता है (सापेक्ष %rbp)।

हालांकि ध्यान दें कि डिफ़ॉल्ट लिंकर स्क्रिप्ट डालता है .rodataऔर .textउसी सेगमेंट में होता है, जिसने निष्पादित किया है, लेकिन कोई लिखित अनुमति नहीं है। इसके साथ मनाया जा सकता है:

readelf -l a.out

जिसमें है:

 Section to Segment mapping:
  Segment Sections...
   02     .text .rodata

17

पहले कोड में, "स्ट्रिंग" एक स्ट्रिंग स्थिरांक है, और स्ट्रिंग स्थिरांक को कभी भी संशोधित नहीं किया जाना चाहिए क्योंकि उन्हें अक्सर केवल मेमोरी में पढ़ने के लिए रखा जाता है। "str" ​​एक पॉइंटर है जिसका उपयोग कंटीन्यू को संशोधित करने के लिए किया जा रहा है।

दूसरे कोड में, "स्ट्रिंग" एक सरणी इनिशियलाइज़र है, जिसके लिए छोटे हाथ की तरह

char str[7] =  { 's', 't', 'r', 'i', 'n', 'g', '\0' };

"str" ​​स्टैक पर आवंटित एक सरणी है और इसे स्वतंत्र रूप से संशोधित किया जा सकता है।


1
स्टैक पर, या डेटा खंड यदि strवैश्विक है या static
गौथियर

12

क्योंकि "whatever"1 उदाहरण के संदर्भ में प्रकार है const char *(भले ही आप इसे नॉन-कास्ट चार * पर असाइन करें), जिसका अर्थ है कि आपको इसे लिखने और लिखने की कोशिश नहीं करनी चाहिए।

संकलक ने मेमोरी के केवल पढ़ने वाले हिस्से में स्ट्रिंग डालकर इसे लागू किया है, इसलिए इसे लिखना एक सेगफॉल्ट उत्पन्न करता है।


8

इस त्रुटि या समस्या को समझने के लिए आपको सबसे पहले बी / डब्ल्यू और पॉइंटर का पता होना चाहिए, इसलिए यहां सबसे पहले मैंने आपको अंतरों को समझा दिया है।

स्ट्रिंग सरणी

 char strarray[] = "hello";

मेमोरी एरे में निरंतर मेमोरी सेल्स में संग्रहित किया जाता [h][e][l][l][o][\0] =>[]है , जिसे 1 चार बाइट आकार की मेमोरी सेल के रूप में संग्रहित किया जाता है, और इस निरंतर मेमोरी सेल्स को स्ट्रैरे के नाम से एक्सेस किया जा सकता है। यहां स्ट्रिंग ऐर में strarrayही स्ट्रिंग के सभी कैरेक्टर होते हैं। यहाँ मामला "hello" इसलिए हम आसानी से अपनी स्मृति सामग्री को प्रत्येक वर्ण को उसके अनुक्रमणिका मान द्वारा बदल सकते हैं

`strarray[0]='m'` it access character at index 0 which is 'h'in strarray

और इसके मूल्य को बदलकर 'm'बहुत कम मूल्य पर बदल दिया गया "mello";

यहाँ एक बात ध्यान देने की है कि हम चरित्र द्वारा चरित्र को बदलकर स्ट्रिंग ऐरे की सामग्री को बदल सकते हैं लेकिन इसे अन्य स्ट्रिंग को सीधे आरंभीकृत नहीं कर सकते जैसे कि strarray="new string"यह अमान्य है

सूचक

जैसा कि हम सभी जानते हैं कि मेमोरी में मेमोरी लोकेशन के लिए पॉइंटर पॉइंट्स, अनइंस्टाल्यूटेड पॉइंटर पॉइंट्स को रैंडम मेमोरी लोकेशन के लिए और इनिशियलाइज़ेशन पॉइंट्स के बाद विशेष मेमोरी लोकेशन पर

char *ptr = "hello";

यहाँ पॉइंटर ptr को स्ट्रिंग के लिए इनिशियलाइज़ किया जाता है "hello"जो निरंतर स्ट्रिंग को केवल मेमोरी (ROM) में संग्रहित किया जाता है ताकि "hello"इसे ROM में स्टोर न किया जा सके

और ptr को स्टैक सेक्शन में स्टोर किया जाता है और निरंतर स्ट्रिंग की ओर इशारा किया जाता है "hello"

इसलिए ptr [0] = 'm' अमान्य है क्योंकि आप केवल पढ़ी गई मेमोरी तक नहीं पहुंच सकते

लेकिन ptr को सीधे अन्य स्ट्रिंग मान से आरंभीकृत किया जा सकता है क्योंकि यह सिर्फ पॉइंटर है, इसलिए यह अपने प्रकार के चर के किसी भी मेमोरी एड्रेस को इंगित कर सकता है

ptr="new string"; is valid

7
char *str = "string";  

उपरोक्त सेट strशाब्दिक मूल्य को इंगित करने के लिए है "string"जो प्रोग्राम की बाइनरी इमेज में हार्ड-कोडित है, जिसे संभवत: मेमोरी में केवल पढ़ने के लिए चिह्नित किया गया है।

इसलिए str[0]=एप्लिकेशन के केवल पढ़ने के लिए कोड लिखने का प्रयास कर रहा है। मुझे लगता है कि यह शायद संकलक पर निर्भर है।


6
char *str = "string";

एक स्ट्रिंग स्ट्रिंगल को पॉइंटर आवंटित करता है, जो संकलक आपके निष्पादन योग्य के गैर-परिवर्तनीय हिस्से में डाल रहा है;

char str[] = "string";

आवंटित करता है और एक स्थानीय सरणी को आरंभीकृत करता है जो कि परिवर्तनीय है


क्या हम ऐसे लिख सकते हैं int *b = {1,2,3) जैसे हम लिखते हैं char *s = "HelloWorld"?
सूरज जैन

6

C FAQ जो @matli से जुड़ा हुआ है, उसका उल्लेख करता है, लेकिन यहां किसी और के पास अभी तक नहीं है, इसलिए स्पष्टीकरण के लिए: यदि एक स्ट्रिंग शाब्दिक (आपके स्रोत में डबल-उद्धृत स्ट्रिंग) का उपयोग वर्ण सरणी को प्रारंभ करने के अलावा कहीं और किया गया है (यानी: @ मार्क का दूसरा उदाहरण, जो सही तरीके से काम करता है), उस स्ट्रिंग को कंपाइलर द्वारा एक विशेष स्टैटिक स्ट्रिंग टेबल में संग्रहित किया जाता है , जो कि एक ग्लोबल स्टैटिक वेरिएबल (रीड-ओनली, ऑफ कोर्स) बनाने के लिए समान है, जो अनिवार्य रूप से अनाम है (जिसका कोई चर नहीं है) नाम ")। केवल पढ़ने के लिए हिस्सा महत्वपूर्ण हिस्सा है, और क्यों @ मार्क का पहला कोड उदाहरण segfaults है।


क्या हम ऐसे लिख सकते हैं int *b = {1,2,3) जैसे हम लिखते हैं char *s = "HelloWorld"?
सूरज जैन

4

 char *str = "string";

लाइन एक पॉइंटर को परिभाषित करती है और इसे शाब्दिक स्ट्रिंग की ओर इंगित करती है। जब आप करते हैं तो शाब्दिक स्ट्रिंग लिखने योग्य नहीं होता है:

  str[0] = 'z';

आपको एक सीजी गलती मिलती है। कुछ प्लेटफार्मों पर, शाब्दिक लेखन योग्य मेमोरी में हो सकता है ताकि आपको एक सेगफॉल्ट दिखाई न दे, लेकिन यह अमान्य कोड है (जिसके परिणामस्वरूप अपरिभाषित व्यवहार होता है)।

रेखा:

char str[] = "string";

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


क्या हम ऐसे लिख सकते हैं int *b = {1,2,3) जैसे हम लिखते हैं char *s = "HelloWorld"?
सूरज जैन

3

स्ट्रिंग स्ट्रिंग जैसे "स्ट्रिंग" को संभवतः आपके निष्पादन योग्य पते के स्थान पर केवल-पढ़ने योग्य डेटा के रूप में आवंटित किया जाता है (अपना संकलक दें या लें)। जब आप इसे छूने जाते हैं, तो यह पता चलता है कि आप इसके स्नान सूट क्षेत्र में हैं और आपको सीग दोष के साथ पता चलता है।

आपके पहले उदाहरण में, आपको उस कॉन्स्टेंट डेटा का एक पॉइंटर मिल रहा है। अपने दूसरे उदाहरण में, आप कास्ट डेटा की एक प्रति के साथ 7 वर्णों की एक सरणी की शुरुआत कर रहे हैं।


2
// create a string constant like this - will be read only
char *str_p;
str_p = "String constant";

// create an array of characters like this 
char *arr_p;
char arr[] = "String in an array";
arr_p = &arr[0];

// now we try to change a character in the array first, this will work
*arr_p = 'E';

// lets try to change the first character of the string contant
*str_p = 'G'; // this will result in a segmentation fault. Comment it out to work.


/*-----------------------------------------------------------------------------
 *  String constants can't be modified. A segmentation fault is the result,
 *  because most operating systems will not allow a write
 *  operation on read only memory.
 *-----------------------------------------------------------------------------*/

//print both strings to see if they have changed
printf("%s\n", str_p); //print the string without a variable
printf("%s\n", arr_p); //print the string, which is in an array. 

1

पहली जगह में, strएक सूचक है जो इंगित करता है "string"। संकलक को स्मृति में उन स्थानों पर स्ट्रिंग शाब्दिक रूप से रखने की अनुमति है जिन्हें आप लिख नहीं सकते हैं, लेकिन केवल पढ़ सकते हैं। (यह वास्तव में एक चेतावनी को ट्रिगर करना चाहिए था, क्योंकि आप एक const char *को असाइन कर रहे हैं char *। क्या आपके पास चेतावनियाँ अक्षम हैं, या क्या आपने सिर्फ उन्हें अनदेखा किया है?)

दूसरे स्थान पर, आप एक सरणी बना रहे हैं, जो कि वह मेमोरी है जिसे आपने पूर्ण एक्सेस प्राप्त किया है, और इसके साथ इनिशियलाइज़ कर रहे हैं "string"। आप char[7]अक्षरों के लिए एक (छह, '' 0 'को समाप्त करने के लिए) बना रहे हैं, और आप इसे पसंद करते हैं।


@Ferruccio,? हां constउपसर्ग चर पढ़ें केवल पढ़ने के लिए
EsmaeelE

सी में स्ट्रिंग शाब्दिक प्रकार होते हैं char [N], नहीं const char [N], इसलिए कोई चेतावनी नहीं है। (आप इसे कम से कम पास करके बदल सकते हैं -Wwrite-strings।)
melpomene

0

मान लें कि तार हैं,

char a[] = "string literal copied to stack";
char *p  = "string literal referenced by p";

पहले मामले में, 'ए' के ​​दायरे में आने पर शाब्दिक की नकल की जानी चाहिए। यहाँ 'a' स्टैक पर परिभाषित एक सरणी है। इसका मतलब है कि स्टैक पर स्ट्रिंग बनाई जाएगी और इसका डेटा कोड (टेक्स्ट) मेमोरी से कॉपी किया जाता है, जो आमतौर पर केवल-पढ़ने के लिए होता है (यह कार्यान्वयन विशिष्ट है, एक कंपाइलर इस रीड-ओनली प्रोग्राम डेटा को रीड-रिएबल मेमोरी में भी रख सकता है )।

दूसरे मामले में, p एक सूचक है जिसे स्टैक (स्थानीय स्कोप) पर परिभाषित किया गया है और एक स्ट्रिंग शाब्दिक (प्रोग्राम डेटा या पाठ) का संदर्भ देते हुए जहां संग्रहीत किया गया है। आमतौर पर ऐसी स्मृति को संशोधित करना अच्छा अभ्यास नहीं है और न ही प्रोत्साहित किया जाता है।


-1

पहले एक निरंतर स्ट्रिंग है जिसे संशोधित नहीं किया जा सकता है। दूसरा आरंभिक मान वाला एक सरणी है, इसलिए इसे संशोधित किया जा सकता है।


-2

खंडन दोष तब होता है जब आप स्मृति को एक्सेस करने का प्रयास करते हैं जो दुर्गम है।

char *str एक स्ट्रिंग के लिए एक संकेतक है जो गैर-परिवर्तनीय है (सीगफॉल्ट होने का कारण)।

जबकि char str[]एक सरणी है और संशोधित किया जा सकता है ..

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.