Char * और const char * में अंतर है?


177

के बीच क्या अंतर है

char* name

जो एक निरंतर स्ट्रिंग शाब्दिक को इंगित करता है, और

const char* name

सी में " निरंतर स्ट्रिंग शाब्दिक" (सी + + नहीं) से क्या मतलब है
gbulmer

1
... चार * नाम एक निरंतर स्ट्रिंग शाब्दिक को इंगित किया जा सकता है
हिममानव

"निरंतर स्ट्रिंग शाब्दिक" में स्थिरांक निरर्थक है, क्योंकि सभी स्ट्रिंग शाब्दिक सिद्धांत निरंतर संस्थाओं में हैं। यह चर की सामग्री है जिसे या तो स्थिर या परिवर्तनशील बनाया जा सकता है। यदि आप "नाम" द्वारा
कपकेक

सिंपल: "चार * नाम" नाम चार करने के लिए एक सूचक है, यानी दोनों को यहां बदला जा सकता है। "const char * name" नाम एक पॉइंटर है जो कॉस्ट चार यानी पॉइंटर बदल सकता है लेकिन चार नहीं।
akD

इन बातों को दायें से बायें पढ़ें।
जियापेंग झांग

जवाबों:


406

char*एक उत्परिवर्ती चरित्र / स्ट्रिंग के लिए एक परस्पर सूचक है ।

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

char* constएक है अपरिवर्तनीय सूचक (यह किसी अन्य स्थान को इंगित नहीं कर सकता) लेकिन , जिस पर यह अंक हैं स्थान की सामग्री परिवर्तनशील

const char* constएक अपरिवर्तनीय सूचक एक अपरिवर्तनीय चरित्र / स्ट्रिंग है।


4
उपरोक्त उल्लिखित कथनों के बाद और उस चर का संदर्भ देकर किसी परिवर्तन के साथ भ्रम को दूर किया जा सकता है।
ankit.karwasra

3
@ ankit.karwasra, आपको एक और याद आती है:char const *
पेसियर

मैं म्यूट चरित्र / स्ट्रिंग के साथ दो विकल्पों को अत्यधिक खतरनाक मानता हूं, क्योंकि आप एक सेग्मेटेशन गलती मेमोरी कर सकते हैं, और यदि आप वास्तव में स्मार्ट हैं तो आप कंप्यूटर को हैक कर सकते हैं। यही कारण है कि कंपाइलरों ने हमेशा उन कार्यान्वयनों में चेतावनी दी है जो मुझे लगता है
डैनियल एन

1
क्या परिवर्तन char *करते समय विभाजन में खराबी नहीं आएगी ?
दिव्यांशु मैथानी

1
इसलिए मैं उपयोग करता हूं constअगर मैं चाहता हूं कि कंपाइलर त्रुटि दे तो क्या मैं भूल गया और गलती से डेटा बदल दिया, है ना?
लेखाकार

43
char *name

आप चार्ट को किस nameबिंदु पर बदल सकते हैं , और यह भी कि वह किस बिंदु पर है।

const char* name

आप चार्ट को किन nameबिंदुओं में बदल सकते हैं , लेकिन आप उस बिंदु पर चार्ट को संशोधित नहीं कर सकते।
सुधार: आप पॉइंटर बदल सकते हैं, लेकिन चार को नहीं , जो nameइंगित करता है ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx , देखें "उदाहरण" )। इस स्थिति में, constविनिर्देशक पर लागू होता हैchar , तारांकन नहीं।

MSDN पृष्ठ और http://en.cppreference.com/w/cpp/language/declarations के अनुसार , constपहले घोषित *-निर्दिष्ट अनुक्रम का हिस्सा है , जबकि constबाद में घोषणाकर्ता *का हिस्सा है।
एक घोषणा विनिर्देश अनुक्रम को कई घोषणाकर्ताओं द्वारा पालन किया जा सकता है, यही कारण है कि जैसा और जैसा const char * c1, c2घोषित c1किया गया है ।const char *c2const char

संपादित करें:

टिप्पणियों से, आपका प्रश्न दो घोषणाओं के बीच अंतर के बारे में पूछ रहा है जब सूचक एक स्ट्रिंग शाब्दिक को इंगित करता है।

उस स्थिति में, आपको चार बिंदुओं के लिए चार को संशोधित नहीं करना चाहिएname , क्योंकि इसका परिणाम अपरिभाषित व्यवहार में हो सकता है । स्ट्रिंग शाब्दिक केवल मेमोरी क्षेत्रों (कार्यान्वयन परिभाषित) को पढ़ने में आवंटित किया जा सकता है और एक उपयोगकर्ता कार्यक्रम को वैसे भी इसे संशोधित नहीं करना चाहिए। ऐसा करने का कोई भी प्रयास अपरिभाषित व्यवहार में परिणाम देता है।

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

ऑनलाइन नमूना उदाहरण:

#include <string.h>
int main()
{
    char *str1 = "string Literal";
    const char *str2 = "string Literal";
    char source[] = "Sample string";

    strcpy(str1,source);    //No warning or error, just Undefined Behavior
    strcpy(str2,source);    //Compiler issues a warning

    return 0;
}

आउटपुट:

cc1: चेतावनियों को त्रुटियों के रूप में व्यवहार किया जा रहा है
prog.c: फ़ंक्शन में 'main':
prog.c: 9: error: 'strcpy' के तर्क 1 को पॉइंटर टार्गेट से क्वालीफायर से हटाता है

सूचना संकलक को दूसरे मामले के लिए चेतावनी देता है लेकिन पहले के लिए नहीं।


धन्यवाद .. मैं लगातार स्ट्रिंग शाब्दिक के साथ मिश्रण कर रहा था, जिसे इस प्रकार परिभाषित किया गया है: char * name = "स्ट्रिंग लिटरल"; "स्ट्रिंगिंग लिटरल" को बदलना अपरिभाषित है ..
आइसमैन

@ user1279782: इर, रुको! क्या आप यहां स्ट्रिंग शाब्दिक की ओर इशारा करते बिंदुओं के बारे में बात कर रहे हैं? उस स्थिति में आपको चार में से किसी भी मामले में चार को संशोधित नहीं करना चाहिएname । इसके परिणामस्वरूप यूबी हो सकता है।
आलोक सेव

हाँ, यह बात थी। तो उस स्थिति में char * name और const char * name समान व्यवहार करता है, है ना?
आइसमैन

4
यह जवाब या तो बेहद अस्पष्ट है या सिर्फ सादा गलत है। मैं व्याख्या करता हूं कि "आप किस नाम के अंक में परिवर्तन नहीं कर सकते हैं, लेकिन आप उस चार को संशोधित कर सकते हैं जिस पर यह इंगित करता है।" : नहीं स्मृति स्थान है कि यह की ओर इशारा करता है, जो सही नहीं है संशोधित करने के लिए सक्षम किया जा रहा सूचक ही संशोधित करने के लिए सक्षम किया जा रहा है, लेकिन जैसा कि ideone.com/6lUY9s : शुद्ध सी के लिए वैकल्पिक रूप से ideone.com/x3PcTP
shroudednight

1
@ ग्रील्डनाइट: आपको अपरिभाषित व्यवहारों के बारे में थोड़ा और जानने की जरूरत है, और इसके बीच अंतर करने की आवश्यकता है: अनुमति दी जानी चाहिए और नहीं होनी चाहिए। :)
आलोक सेव

16
char mystring[101] = "My sample string";
const char * constcharp = mystring; // (1)
char const * charconstp = mystring; // (2) the same as (1)
char * const charpconst = mystring; // (3)

constcharp++; // ok
charconstp++; // ok
charpconst++; // compile error

constcharp[3] = '\0'; // compile error
charconstp[3] = '\0'; // compile error
charpconst[3] = '\0'; // ok

// String literals
char * lcharp = "My string literal";
const char * lconstcharp = "My string literal";

lcharp[0] = 'X';      // Segmentation fault (crash) during run-time
lconstcharp[0] = 'X'; // compile error

// *not* a string literal
const char astr[101] = "My mutable string";
astr[0] = 'X';          // compile error
((char*)astr)[0] = 'X'; // ok

1
आपका कोई भी संकेत प्रश्न के अनुसार "निरंतर स्ट्रिंग शाब्दिक" को इंगित नहीं करता है।
कैफे

यह ध्यान देने योग्य है कि char *मूल्य बदलने से विभाजन की गलती होती है क्योंकि हम एक स्ट्रिंग शाब्दिक (जो कि केवल मेमोरी में मौजूद है) को संशोधित करने की कोशिश कर रहे हैं
दिव्यांशु मैथानी

10

न तो मामले में आप एक स्ट्रिंग शाब्दिक को संशोधित कर सकते हैं, भले ही उस स्ट्रिंग शाब्दिक को सूचक के रूप में घोषित किया गया हो char *या नहीं const char *

हालाँकि, अंतर यह है कि यदि पॉइंटर है const char *तो कंपाइलर को डायग्नोस्टिक देना होगा यदि आप इंगित किए गए मान को संशोधित करने का प्रयास करते हैं, लेकिन यदि पॉइंटर है char *तो ऐसा नहीं है।


1
"न तो मामले में आप किसी स्ट्रिंग शाब्दिक को संशोधित कर सकते हैं, चाहे वह ... [इसे] चार * या कास्ट चार के रूप में घोषित किया गया है" "मैं मानता हूं कि प्रोग्रामर को कोशिश नहीं करनी चाहिए, लेकिन क्या आप कह रहे हैं कि हर सी कंपाइलर, हर पर प्लेटफ़ॉर्म कोड को अस्वीकार कर देगा, कोड को रन समय पर विफल करने की व्यवस्था करेगा, या कुछ और? मेरा मानना ​​है कि, एक फ़ाइल की परिभाषा और प्रारंभिककरण हो सकता है, और दूसरी फ़ाइल में हो सकता है extern ... nameऔर हो सकता है *name = 'X';। 'उचित ऑपरेटिंग सिस्टम' पर, यह विफल हो सकता है, लेकिन एम्बेडेड सिस्टम पर, मैं यह अपेक्षा करूंगा कि यह कुछ प्लेटफॉर्म / कंपाइलर विशिष्ट हो।
गॉलमर

@gbulmer: आप सही C प्रोग्राम में स्ट्रिंग शाब्दिक को संशोधित नहीं कर सकते। एक गलत C प्रोग्राम जो परिणाम देता है, न तो यहां है और न ही है।
कैफे

@gbulmer: एक उपयोगी परिभाषा एक प्रोग्राम है जो सी भाषा मानक द्वारा निर्दिष्ट किसी भी बाधा को नहीं तोड़ता है। दूसरे शब्दों में, एक स्ट्रिंग शाब्दिक रूप से संशोधित करने वाला प्रोग्राम उसी तरह से गलत है जैसे कि एक शून्य सूचक को dereferences करता है या किसी विभाजन को निष्पादित करता है वह गलत है।
कैफे

कैफे - मैंने सोचा था कि आप का मतलब क्या हो सकता है। फिर "न तो मामले में आप एक स्ट्रिंग शाब्दिक को संशोधित कर सकते हैं" यह बताते हुए लगता है। यह कहना सटीक होगा "दोनों मामलों में, सी भाषा मानक द्वारा निर्दिष्ट बाधाएं, चाहे जो भी हो, टूट गई हैं .... सभी मामलों में मानक के उल्लंघनों की पहचान करने के लिए संकलक या रन सिस्टम के लिए संभव नहीं है।" मुझे लगता है कि मानक स्थिति लेता है कि प्रभाव अपरिभाषित है?
गालमर

1
जब कोई मानक किसी भी तरह से जोर नहीं दे सकता है, तो मुझे लगता है कि व्यवहार को 'अपरिभाषित' के रूप में परिभाषित करना बिल्कुल सही सीमा और सहायक लगता है। संबंध का दावा करने के लिए एक 'सही सी कार्यक्रम' ' नहीं कर सकते हैं एक अशक्त संकेतक भिन्नता' हॉल्टिंग समस्या साबित हो के बराबर लग रहा है। लेकिन मुझे कोई आपत्ति नहीं है। मैं ऐसा नहीं करूंगा और उम्मीद करूंगा कि इसके साथ '
स्कोट

4

मामला एक:

char *str = "Hello";
str[0] = 'M'  //Warning may be issued by compiler, and will cause segmentation fault upon running the programme

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

मामला 2:

const char *str = "Hello";
str[0] = 'M'  //Compile time error

मामला 3:

char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".

2

पहला आप वास्तव में बदल सकते हैं यदि आप चाहते हैं, दूसरा आप नहीं कर सकते। constशुद्धता के बारे में पढ़ें (अंतर के बारे में कुछ अच्छे मार्गदर्शक हैं)। वहाँ भी है char const * nameजहाँ आप इसे निरस्त नहीं कर सकते।


वास्तव में क्या बदल सकता है?
अंती हापाला

2

सवाल यह है कि क्या अंतर है

char *name

जो एक निरंतर स्ट्रिंग शाब्दिक को इंगित करता है, और

const char *cname

Ie दिया गया

char *name = "foo";

तथा

const char *cname = "foo";

2 में बहुत अंतर नहीं है और दोनों को सही देखा जा सकता है। सी कोड की लंबी विरासत के कारण, स्ट्रिंग शाब्दिकों के पास एक प्रकार का है char[], नहीं const char[], और बहुत सारे पुराने कोड हैं जो इसी तरह स्वीकार करते char *हैं const char *, भले ही वे तर्कों को संशोधित न करें।

सामान्य रूप से 2 का मुख्य अंतर यह है कि *cnameया cname[n]प्रकार के lvalues ​​का मूल्यांकन करेगा const char, जबकि *nameया name[n]प्रकार के lvalues ​​का मूल्यांकन करेगा char, जो कि परिवर्तनीय lvalues ​​हैं । एक संकेंद्रित संदेश का उत्पादन करने के लिए एक अनुरूप संकलक की आवश्यकता होती है यदि असाइनमेंट का लक्ष्य एक परिवर्तनीय अंतराल नहीं है ; यह प्रकार के अंतराल को असाइनमेंट पर कोई चेतावनी देने की आवश्यकता नहीं है char:

name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message

संकलक को किसी भी मामले में संकलन को रोकने की आवश्यकता नहीं है ; यह पर्याप्त है कि यह असाइनमेंट के लिए एक चेतावनी पैदा करता है cname[0]। परिणामी कार्यक्रम एक सही कार्यक्रम नहीं है । निर्माण का व्यवहार अपरिभाषित है । यह दुर्घटनाग्रस्त हो सकता है, या इससे भी बदतर हो सकता है, यह दुर्घटनाग्रस्त नहीं हो सकता है, और स्मृति में स्ट्रिंग शाब्दिक बदल सकता है।


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