Char * const और const चार * में क्या अंतर है?


279

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

char * const 

तथा

const char *


8
"कॉन्स्ट" के बाईं ओर पहली चीज जो स्थिर है। यदि "कॉन्स्ट" सबसे बायीं ओर सबसे दूर की चीज है, तो इसके दाईं ओर पहली चीज जो स्थिर है।
कपकेक

4
एक दोस्ताना टिप के रूप में, यह कभी न भूलें कि सीडीसीएल एक चीज है।
ब्रैडेन बेस्ट

वहाँ एक और चार कास्ट * जो अपवाद का वापसी प्रकार है :: क्या ()
झांग

जवाबों:


363

अंतर यह है कि const char *एक के लिए एक सूचक है const char, जबकि char * constएक को लगातार सूचक है char

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

वहाँ भी है एक

const char * const

जो निरंतर चारित्र के लिए एक स्थिर सूचक है (इसलिए इसके बारे में कुछ भी नहीं बदला जा सकता है)।

ध्यान दें:

निम्नलिखित दो रूप समतुल्य हैं:

const char *

तथा

char const *

इसका सटीक कारण C ++ मानक में वर्णित है, लेकिन भ्रम को ध्यान में रखना और उससे बचना महत्वपूर्ण है। मैं कई कोडिंग मानकों को जानता हूं जो पसंद करते हैं:

char const

ऊपर

const char

(पॉइंटर के साथ या बिना) ताकि constएलिमेंट का प्लेसमेंट पॉइंटर के समान हो const


6
क्या यह नोट करना सार्थक होगा कि यदि एक ही घोषणा में कई चर निर्दिष्ट किए जाते हैं तो क्या होगा? मेरा मानना है कि const int *foo,*bar;दोनों घोषणा करेंगे fooऔर barहोना करने के लिए int const *है, लेकिन int const *foo, *barघोषणा करेंगे fooएक होने के लिए int const *और barहोना करने के लिए int *। मुझे लगता है typedef int * intptr; const intptr foo,bar;कि दोनों चर होने की घोषणा करेंगे int * const; मैं बिना किसी टाइप किए हुए उस प्रकार के दो चर बनाने के लिए संयुक्त घोषणा का उपयोग करने का कोई तरीका नहीं जानता।
सुपरकैट

1
@ सुपरकैट I believe const int *foo,*bar; would declare both foo and bar to be int const *: हाँ। but int const *foo, *bar would declare foo to be a int const * and bar to be int *: नहीं! यह पिछले मामले जैसा ही होगा। (देखें ideone.com/RsaB7n जहां आपको फू और बार दोनों के लिए समान त्रुटि मिलती है)। I think typedef int * intptr; const intptr foo,bar; would declare both variables to be int * const: हाँ। I don't know any way to use a combined declaration to create two variables of that type without a typedef: अच्छा int *const foo, *const bar;। सी घोषणा सिंटैक्स ...
gx_

@gx_: तो मैं गलत था - मेरी अनिश्चितता थी कि मैंने सुझाव दिया कि यह कहना मददगार हो सकता है कि नियम क्या हैं। क्या होगा int const *foo, *volatile barकरने के लिए क्या bar? इसे constऔर बनाओ volatile? मुझे याद है कि घोषित-चर नामों और उनके प्रकारों के पास्कल को अलग-अलग करने से (पूर्णांक को var foo: ^Array[3..4] of ^Integerइंगित करने वाले बिंदुओं की ओर एक सूचक) होगा ; `। यह C में कुछ मजाकिया नेस्टेड स्तरहीन चीज़ होगी, मुझे लगता है।
सुपरकैट

3
@supercat (ओह, सी ही है, खेद सी ++ कोड लिंक के लिए, मैं एक सी ++ सवाल से यहाँ मिल गया) यह सब क्या है सी घोषणा वाक्य रचना , एक ( "शुद्ध") के साथ प्रकार भाग एक के बाद declarator । में " int const *foo, *volatile bar" प्रकार का हिस्सा है int const(पहले बंद हो जाता है *) और घोषणाकर्ता हैं *foo(अभिव्यक्ति *fooको निरूपित करेंगे int const) और *volatile bar; दाईं-बाईं ओर पढ़ना ( सीवी-क्वालिफायर ), fooएक करने के लिए एक सूचक है स्थिरांक पूर्णांक, और barएक है अस्थिर एक सूचक स्थिरांक पूर्णांक (सूचक ही अस्थिर है, उठाई पूर्णांक स्थिरांक [के रूप में पहुँचा] है)।
gx_

@ सुपरफ़ैट और "पूर्णांक के लिए संकेत की एक सरणी के लिए एक संकेतक" के रूप में (मैं पास्कल को नहीं जानता, [3..4]वाक्यविन्यास के बारे में निश्चित नहीं है , तो चलो 10 तत्वों की एक सरणी लेते हैं) int *(*foo)[10];:। यह एक अभिव्यक्ति के रूप में इसके (भविष्य के) उपयोग को प्रतिबिंबित करता है: *(*foo)[i]( iश्रेणी में पूर्णांक के साथ ) [0, 10)अर्थात [0, 9]पहले fooसरणी में प्राप्त करने के लिए dereference होगा , फिर सूचकांक में तत्व का उपयोग करें i(क्योंकि []उपसर्ग की तुलना में पोस्टफ़ायर तंग को बांधता है *), फिर यह तत्व एक उपज int(देखें ideone.com/jgjIjR )। लेकिन typedefयह आसान बनाता है (देखें ideone.com/O3wb7d )।
gx_

102

भ्रम से बचने के लिए, हमेशा संलग्न रहें को अपीयर करें।

int       *      mutable_pointer_to_mutable_int;
int const *      mutable_pointer_to_constant_int;
int       *const constant_pointer_to_mutable_int;
int const *const constant_pointer_to_constant_int;

10
क्यों? "भ्रम से बचने के लिए" यह नहीं समझाता कि भ्रम मेरे लिए क्या है।
एंड्रयू वीर

14
@ और: मैं स्थिरता और इस तरह पठनीयता पर इशारा कर रहा था। सभी प्रकार के क्वालीफायर लिखना, ताकि वे संशोधित करें कि उनके बाएं, हमेशा , मैं क्या उपयोग करता हूं।
डायपरir

1
वास्तव में यह उस विषय पर सबसे अच्छा जवाब है जो मैंने SO
ट्रैप

8
एक कोड मानक के रूप में, मैंने शायद ही कभी इस शैली का सामना किया है और इसलिए इसे अपनाने की संभावना नहीं है। हालाँकि एक शिक्षण उपकरण के रूप में, यह उत्तर बहुत मददगार था! (इसलिए मेरा अनुमान है कि यह बहुत सामान्य शैली नहीं है।)
natevw

8
@ एला: pप्रकार से संबंधित नहीं है (const int *const):। बेहतर या बदतर (बदतर अगर आप मुझसे पूछते हैं) के लिए, सी और सी ++ दोनों में, कांस्ट क्वालिफायर, पोस्टफिक्स होने का मतलब है: सीएफ कॉन्स्टेबल सदस्य फ़ंक्शन void foo(int a) const;। घोषित करने की संभावना const intनियम के बजाय अपवाद है।
दीपिर

44

const हमेशा उस चीज़ को संशोधित करता है जो इसके पहले आती है (इसके बाईं ओर), EXCEPT जब यह एक प्रकार की घोषणा में पहली बात है, जहाँ यह इसके बाद आने वाली चीज़ को संशोधित करता है (इसके दाईं ओर)।

तो ये दोनों समान हैं:

int const *i1;
const int *i2;

वे एक करने के लिए संकेत परिभाषित करते हैं const int। आप कहां i1और कैसे बदल सकते हैंi2 बिंदुओं , लेकिन आप उनके द्वारा बताए गए मान को नहीं बदल सकते।

यह:

int *const i3 = (int*) 0x12345678;

constएक पूर्णांक के लिए एक सूचक को परिभाषित करता है और इसे स्मृति स्थान 12345678 पर इंगित करने के लिए आरम्भ करता है। आप intपता 12345678 पर मान बदल सकते हैं , लेकिन आप उस पते को नहीं बदल सकते हैं जो i3इंगित करता है।


22

18

const char*एक निरंतर चरित्र के
char* constलिए एक सूचक है एक चरित्र के
const char* constलिए एक निरंतर सूचक एक निरंतर चरित्र के लिए एक निरंतर सूचक है


9

अंगूठे का नियम: दाईं से बाईं ओर परिभाषा पढ़ें!


const int *foo;

मतलब " fooअंक ( *) intजो बदल नहीं सकता ( const)"।
प्रोग्रामर के लिए इसका मतलब है "मैं किन बिंदुओं के मूल्य को नहीं बदलूंगा foo"।

  • *foo = 123;या foo[0] = 123;अमान्य होगा।
  • foo = &bar; की अनुमति है।

int *const foo;

मीन्स " fooनहीं बदल सकते ( const) और पॉइंट्स ( *) टू ए int"।
प्रोग्रामर के लिए इसका मतलब है "मैं स्मृति पते को नहीं बदलूंगा जो fooसंदर्भित करता है"।

  • *foo = 123;या foo[0] = 123;अनुमति है।
  • foo = &bar; अमान्य होगा।

const int *const foo;

मतलब "जो fooनहीं बदल सकता है ( const) और अंक ( *) intजो बदल नहीं सकते ( const)"।
प्रोग्रामर के लिए इसका मतलब है "मैं न तो किस बिंदु के मूल्य को बदलूंगा foo, और न ही उस पते को fooबदलूंगा जो संदर्भित करता है"।

  • *foo = 123;या foo[0] = 123;अमान्य होगा।
  • foo = &bar; अमान्य होगा।

8
  1. const char * x Here X मूल रूप से एक चरित्र सूचक है जो एक स्थिर मान की ओर इशारा करता है

  2. char * const x वर्ण सूचक को संदर्भित करता है जो स्थिर है, लेकिन यह जिस स्थान को इंगित कर रहा है वह परिवर्तन हो सकता है।

  3. const char * const x 1 और 2 का संयोजन है, इसका मतलब यह एक निरंतर चरित्र सूचक है जो निरंतर मान की ओर इशारा करता है।

  4. const * char x एक संकलक त्रुटि का कारण बनेगा। यह घोषित नहीं किया जा सकता है।

  5. char const * x बिंदु 1 के बराबर है।

अंगूठे का नियम अगर कास्ट वैर नाम के साथ है तो पॉइंटर स्थिर रहेगा लेकिन पॉइंटिंग लोकेशन को बदला जा सकता है , अन्यथा पॉइंटर निरंतर स्थान पर इंगित करेगा और पॉइंटर किसी अन्य स्थान पर इंगित कर सकता है लेकिन पॉइंटिंग स्थान सामग्री को परिवर्तित नहीं किया जा सकता है


1
"चार * कास्ट x वर्ण सूचक को संदर्भित करता है जो स्थिर है, लेकिन वह जिस स्थान को इंगित कर रहा है वह परिवर्तन हो सकता है।" गलत। स्थान पर दिए गए मूल्य को स्थान ही नहीं बदला जा सकता है।
कृपया हेल्प

3

पहले एक वाक्य रचना त्रुटि है। शायद आप के बीच का अंतर था

const char * mychar

तथा

char * const mychar

उस स्थिति में, पहला डेटा के लिए एक पॉइंटर है जो बदल नहीं सकता है, और दूसरा एक पॉइंटर है जो हमेशा एक ही पते पर इंगित करेगा।


3

एक और अंगूठा नियम यह जांचने के लिए है कि कॉन्स्ट कहां है :

  1. पहले = => संग्रहीत मूल्य स्थिर है
  2. के बाद * => सूचक स्वयं स्थिर है

3

उत्तर की बहुत सारी विशिष्ट तकनीकों, अंगूठे के नियम आदि को प्रदान करने के लिए चर घोषणा के इस विशेष उदाहरण को समझते हैं। लेकिन किसी भी घोषणा को समझने की एक सामान्य तकनीक है:

दक्षिणावर्त / सर्पिल नियम

ए)

const char *a;

क्लॉकवाइज / सर्पिल नियम के अनुसार, aचरित्र के लिए पॉइंटर है जो निरंतर है। जिसका मतलब है कि चरित्र स्थिर है लेकिन सूचक बदल सकता है। यानी a = "other string";ठीक है लेकिनa[2] = 'c'; संकलन करने में विफल रहेगा

बी)

char * const a;

नियम के अनुसार, aएक चरित्र के लिए कास्ट पॉइंटर है। यानी आप कर सकते हैं a[2] = 'c';लेकिन आप नहीं कर सकतेa = "other string";


1
दाएं-बाएं नियम के रूप में भी जाना जाता है (कम से कम यह है कि मैंने इसे कैसे सीखा): jdurrett.ba.ttu.edu/3345/handouts/RL-rule.html
टॉमस प्रूजिना

(बहुत बेहतर होगा यदि उत्तर का सार एक लिंक के पीछे छिपा नहीं होगा, यहां पाठ के साथ भी नहीं उद्धृत किया गया है, या कम से कम संदर्भ में, इसकी किसी भी बारीकियों से परे, एक सामान्य "नियम के अनुसार"।)
SZ।

@Sz। क्या आपके पास यहां कोई विशिष्ट भ्रम है जिसे मैं स्पष्ट कर सकता हूं? नियम को जानने के बाद वास्तव में इसके लिए बहुत कुछ नहीं है।
PnotNP

1

मुझे लगता है कि आप का मतलब है चार कास्ट * और चार * कास्ट।

पहला, कास्ट चार *, एक स्थिर चरित्र का सूचक है। पॉइंटर ही म्यूटेबल है।

दूसरा, चार * कास्ट एक चरित्र के लिए एक निरंतर सूचक है। पॉइंटर बदल नहीं सकता है, यह चरित्र को इंगित कर सकता है।

और फिर const char * const होता है जहां पॉइंटर और कैरेक्टर नहीं बदल सकते।


आपके पहले दो वास्तव में एक ही हैं और आपका तीसरा एक संकलक त्रुटि है :)
workmad3

1

यहाँ कोड के साथ एक विस्तृत विवरण दिया गया है

/*const char * p;
char * const p; 
const char * const p;*/ // these are the three conditions,

// const char *p;const char * const p; pointer value cannot be changed

// char * const p; pointer address cannot be changed

// const char * const p; both cannot be changed.

#include<stdio.h>

/*int main()
{
    const char * p; // value cannot be changed
    char z;
    //*p = 'c'; // this will not work
    p = &z;
    printf(" %c\n",*p);
    return 0;
}*/

/*int main()
{
    char * const p; // address cannot be changed
    char z;
    *p = 'c'; 
    //p = &z;   // this will not work
    printf(" %c\n",*p);
    return 0;
}*/



/*int main()
{
    const char * const p; // both address and value cannot be changed
    char z;
    *p = 'c'; // this will not work
    p = &z; // this will not work
    printf(" %c\n",*p);
    return 0;
}*/

@reese moore धन्यवाद।
मेघराज

1
// Some more complex constant variable/pointer declaration.
// Observing cases when we get error and warning would help
// understanding it better.

int main(void)
{
  char ca1[10]= "aaaa"; // char array 1
  char ca2[10]= "bbbb"; // char array 2

  char *pca1= ca1;
  char *pca2= ca2;

  char const *ccs= pca1;
  char * const csc= pca2;
  ccs[1]='m';  // Bad - error: assignment of read-only location ‘*(ccs + 1u)’
  ccs= csc;    // Good

  csc[1]='n';  // Good
  csc= ccs;    // Bad - error: assignment of read-only variable ‘csc’

  char const **ccss= &ccs;     // Good
  char const **ccss1= &csc;    // Bad - warning: initialization from incompatible pointer type

  char * const *cscs= &csc;    // Good
  char * const *cscs1= &ccs;   // Bad - warning: initialization from incompatible pointer type

  char ** const cssc=   &pca1; // Good
  char ** const cssc1=  &ccs;  // Bad - warning: initialization from incompatible pointer type
  char ** const cssc2=  &csc;  // Bad - warning: initialization discards ‘const’
                               //                qualifier from pointer target type

  *ccss[1]= 'x'; // Bad - error: assignment of read-only location ‘**(ccss + 8u)’
  *ccss= ccs;    // Good
  *ccss= csc;    // Good
  ccss= ccss1;   // Good
  ccss= cscs;    // Bad - warning: assignment from incompatible pointer type

  *cscs[1]= 'y'; // Good
  *cscs= ccs;    // Bad - error: assignment of read-only location ‘*cscs’
  *cscs= csc;    // Bad - error: assignment of read-only location ‘*cscs’
  cscs= cscs1;   // Good
  cscs= cssc;    // Good

  *cssc[1]= 'z'; // Good
  *cssc= ccs;    // Bad - warning: assignment discards ‘const’
                 //                qualifier from pointer target type
  *cssc= csc;    // Good
  *cssc= pca2;   // Good
  cssc= ccss;    // Bad - error: assignment of read-only variable ‘cssc’
  cssc= cscs;    // Bad - error: assignment of read-only variable ‘cssc’
  cssc= cssc1;   // Bad - error: assignment of read-only variable ‘cssc’
}

1
  1. लगातार पॉइंटर : एक निरंतर पॉइंटर पूरे प्रोग्राम के दौरान संबंधित डेटा प्रकार के केवल एक ही चर को इंगित कर सकता है। हम पॉइंटर द्वारा इंगित चर के मूल्य को बदल सकते हैं। प्रारंभिक घोषणा के समय के दौरान प्रारंभिक किया जाना चाहिए।

वाक्य - विन्यास:

datatype *const var;

char *const इस मामले के तहत आता है।

/*program to illustrate the behaviour of constant pointer */

#include<stdio.h>
int main(){
  int a=10;
  int *const ptr=&a;
  *ptr=100;/* we can change the value of object but we cannot point it to another variable.suppose another variable int b=20; and ptr=&b; gives you error*/
  printf("%d",*ptr);
  return 0;
}
  1. एक कॉस्ट मान को इंगित करता है: इसमें एक पॉइंटर संबंधित प्रकार के किसी भी चर को इंगित कर सकता है लेकिन हम उस विशिष्ट समय में पॉइंटर द्वारा बताई गई वस्तु के मूल्य को बदल नहीं सकते हैं।

वाक्य - विन्यास:

const datatype *varया datatype const *var

const char* इस मामले के तहत आता है।

/* program to illustrate the behavior of pointer to a constant*/

   #include<stdio.h>
   int main(){
       int a=10,b=20;
       int const *ptr=&a;
       printf("%d\n",*ptr);
       /*  *ptr=100 is not possible i.e we cannot change the value of the object pointed by the pointer*/
       ptr=&b;
       printf("%d",*ptr);
       /*we can point it to another object*/
       return 0;
    }

1

char * const और const चार *?

  1. एक निरंतर मूल्य की ओर इशारा करते हुए

const char * p; // मान को बदला नहीं जा सकता

  1. एक मूल्य के लिए लगातार सूचक

char * const p; // पता नहीं बदला जा सकता है

  1. निरंतर मान के लिए सूचक

const char * const p; // दोनों को बदला नहीं जा सकता।


1

constसंशोधक अपनी बाईं ओर तुरंत पद के लिए आवेदन किया है। इसका एकमात्र अपवाद यह है कि जब इसके बाईं ओर कुछ भी नहीं है, तो यह उस पर लागू होता है जो इसके दाईं ओर तुरंत है।

ये "समतुल्य सूचक को स्थिरांक" कहने के सभी समान तरीके हैं char:

  • const char * const
  • const char const *
  • char const * const
  • char const const *

क्या यह संकलक निर्भर है? gcc "const char const *" और "const const char *" और "char const const *" का एक ही परिणाम -> सूचक अन्य स्थान की ओर इशारा कर सकता है।
cosinus0

1

दो नियम

  1. If const is between char and *, it will affect the left one.
  2. If const is not between char and *, it will affect the nearest one.

जैसे

  1. char const *. This is a pointer points to a constant char.
  2. char * const. This is a constant pointer points to a char.

1

मैं यह बताना चाहता हूं कि किसी चर की ओर इशारा करने वाले सूचक int const *(या const int *) का उपयोग करना नहीं है const int, लेकिन यह चर हैconst इस विशिष्ट सूचक के लिए है।

उदाहरण के लिए:

int var = 10;
int const * _p = &var;

ऊपर दिए गए कोड पूरी तरह से ठीक हैं। _pएक constचर के लिए अंक , हालांकि varखुद स्थिर नहीं है।


1

मुझे चेक बुक से सी के बारे में याद है: घोषणा को पढ़ें कि आप चर से शुरू करते हैं और बाएं जाते हैं। के लिए

char * const a;

आप के रूप में पढ़ सकते हैं: " aका प्रकार स्थिर सूचक है char",

char const * a;

आप इस प्रकार पढ़ सकते हैं: " aटाइप चर के निरंतर चर के लिए एक सूचक है। मुझे आशा है कि यह मदद करता है।

बक्शीश:

const char * const a;

आप पढ़ेंगे के रूप aमें निरंतर सूचक प्रकार चर के निरंतर चर के लिए है।

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