C ++ और C में फ़ंक्शन मापदंडों के रूप में 'const int' बनाम 'int const'


116

विचार करें:

int testfunc1 (const int a)
{
  return a;
}

int testfunc2 (int const a)
{
  return a;
}

क्या ये दोनों कार्य हर पहलू में समान हैं या इनमें कोई अंतर है?

मुझे C भाषा के जवाब में दिलचस्पी है, लेकिन अगर C ++ भाषा में कुछ दिलचस्प है, तो मैं भी जानना चाहूंगा।


क्या C में अभी कोई कॉन्स्टेबल कीवर्ड है? वहाँ नहीं हुआ करता था, लेकिन मैं सी 99 मानक से परिचित नहीं हूँ।
ओनोरियो कैटेनियास

8
आप होने की जरूरत नहीं है। C90 काफी है। हालांकि यह मूल K & R C में नहीं था।
मार्क बेकर

3
यह C89 और ANSI में एक कीवर्ड है। मुझे नहीं पता कि यह केर्निंघम और रिची दिनों में एक कीवर्ड था।
बजे निल्स पिपेनब्रिंक

7
यह साइट "c gibberish" का अंग्रेजी cdecl.org
Motti

5
मैं कहता हूँ "C gibberish to English gibberish", लेकिन फिर भी अच्छा :)
Kos

जवाबों:


175

const Tऔर T constसमान हैं। सूचक प्रकारों के साथ यह अधिक जटिल हो जाता है:

  1. const char* एक स्थिर करने के लिए एक सूचक है char
  2. char const* एक स्थिर करने के लिए एक सूचक है char
  3. char* const एक (निरंतर) के लिए एक निरंतर सूचक है char

दूसरे शब्दों में, (1) और (2) समान हैं। केवल सूचक (बल्कि pointee से) बनाने का तरीका constएक suffix- उपयोग करने के लिए है const

यही कारण है कि बहुत से लोग हमेशा constटाइप ("ईस्ट कास्ट" स्टाइल) के दाईं ओर रखना पसंद करते हैं : यह अपने स्थान को टाइप के सापेक्ष सुसंगत और आसान बना देता है (यह विशेष रूप से शुरुआती लोगों को सिखाना आसान बनाता है। )।


2
C के पास const है, जो दिया गया है: static const char foo [] = "foo"; आप बेहतर फू को नहीं बदल सकते।
जेम्स एंटिल

4
K & R C में कोई समस्‍या नहीं है; C90 (और C99) करता है। यह C ++ की तुलना में थोड़ा सीमित है, लेकिन यह उपयोगी है।
मार्क बेकर

क्या यह संदर्भों के लिए भी सही है?
केन

1
@ हाँ, यह वही है।
कोनराड रुडोल्फ

1
@ étale-cohomology अच्छा बिंदु, जोड़ा गया। वहाँ सब साथ होना चाहिए था।
कोनराड रुडोल्फ

339

घोषणा को पीछे की ओर (दाएं-बाएं) पढ़ने के लिए चाल है:

const int a = 1; // read as "a is an integer which is constant"
int const a = 1; // read as "a is a constant integer"

दोनों एक ही चीज हैं। इसलिए:

a = 2; // Can't do because a is constant

जब आप अधिक जटिल घोषणाओं से निपट रहे हों तो रीडिंग बैकवर्ड ट्रिक विशेष रूप से काम में आती है:

const char *s;      // read as "s is a pointer to a char that is constant"
char c;
char *const t = &c; // read as "t is a constant pointer to a char"

*s = 'A'; // Can't do because the char is constant
s++;      // Can do because the pointer isn't constant
*t = 'A'; // Can do because the char isn't constant
t++;      // Can't do because the pointer is constant

5
"चार कास्ट * यू" के बारे में क्या? क्या यह "एक पॉइंटर टू ए कंटेंट कैरेक्टर" या "पॉइंटर है जो एक कैरेक्टर के लिए स्थिर है" पढ़ता है? अस्पष्ट लगता है। मानक पूर्व को कहता है, लेकिन यह पता लगाने के लिए, आपको पूर्वता और सहानुभूति नियमों को ध्यान में रखना होगा।
पैन्योटिस कराबैसिस

5
@PanayiotisKarabassis सभी को विशेषण की एक श्रृंखला के रूप में माना जाना चाहिए, बिना किसी स्थान की अदला-बदली के। char const *, बाएं से दाएं पढ़ा जाता है: "पॉइंटर, कास्ट, चार"। यह कास्ट चेर का सूचक है। जब आप कहते हैं "एक सूचक जो स्थिर है", "स्थिर" विशेषण सूचक पर है। तो, उस स्थिति के लिए, आपके विशेषणों की सूची वास्तव में होनी चाहिए: "कास्ट, पॉइंटर, चार"। लेकिन आप सही कह रहे हैं, इस चाल में अस्पष्टता है। यह वास्तव में एक "चाल" है, एक निश्चित "नियम" से अधिक है।
एटल गोराल

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

@Martin JH: वे typedefs के माध्यम से नहीं तोड़ा जा सकता है? और / या अप्रत्यक्ष को खत्म करने के लिए संदर्भ का उपयोग कर?
पीटर मोर्टेंसन

14

इसमें कोई फर्क नही है। वे दोनों "ए" को पूर्णांक घोषित करते हैं जिसे बदला नहीं जा सकता।

वह स्थान जहाँ अंतर दिखाई देने लगता है, जब आप पॉइंटर्स का उपयोग करते हैं।

ये दोनों:

const int *a
int const *a

घोषित "a" एक पूर्णांक के लिए एक संकेतक है जो नहीं बदलता है। "a" को सौंपा जा सकता है, लेकिन "* a" नहीं कर सकता।

int * const a

"a" को पूर्णांक के लिए एक स्थिर सूचक घोषित करता है। * "ए" को सौंपा जा सकता है, लेकिन "ए" नहीं कर सकता।

const int * const a

निरंतर पूर्णांक के लिए "a" को एक स्थिर सूचक बताता है। न तो "ए" और न ही "* ए" को सौंपा जा सकता है।

static int one = 1;

int testfunc3 (const int *a)
{
  *a = 1; /* Error */
  a = &one;
  return *a;
}

int testfunc4 (int * const a)
{
  *a = 1;
  a = &one; /* Error */
  return *a;
}

int testfunc5 (const int * const a)
{
  *a = 1;   /* Error */
  a = &one; /* Error */
  return *a;
}

अंतिम उदाहरण सबसे सरल व्याख्या है, महान!
exru

7

प्रकाश सही है कि घोषणाएं समान हैं, हालांकि सूचक मामले की थोड़ी अधिक व्याख्या क्रम में हो सकती है।

"const int * p" एक int का सूचक है जो उस सूचक के माध्यम से int को बदलने की अनुमति नहीं देता है। "int * const p" एक int का सूचक है जिसे दूसरे int को इंगित करने के लिए नहीं बदला जा सकता है।

Https://isocpp.org/wiki/faq/const-correctness#const-ptr-vs-ptr-const देखें ।


लंगर ("faq-18.5) टूट गया है। इसे किसको संदर्भित करना चाहिए (" कॉन्स्ट "और" * "के साथ कई हैं)?
पीटर मोर्टेंसन

@PeterMortensen: हाँ, लिंक सड़ांध। धन्यवाद। मैंने लिंक अपडेट किया।
फ्रेड लार्सन

5

const intके समान है int const, जैसा कि सी में सभी स्केलर प्रकारों के साथ सच है। सामान्य तौर पर, स्केलर फ़ंक्शन पैरामीटर को घोषित करने की constआवश्यकता नहीं होती है, क्योंकि सी के कॉल-बाय-वैल्यू शब्दार्थ का अर्थ है कि चर में कोई भी परिवर्तन इसके संलग्न फ़ंक्शन के लिए स्थानीय हैं।


4

यह एक सीधा जवाब नहीं है, लेकिन संबंधित टिप है। चीजों को सीधे रखने के लिए, मैं हमेशा " constबाहरी पर डाल" संवहन का उपयोग करता हूं , जहां "बाहर" से मेरा मतलब है कि बाईं तरफ या बहुत दूर तक। इस तरह से कोई भ्रम नहीं है - पास की चीज (या तो प्रकार या *) पर कास्ट लागू होता है । उदाहरण के लिए,



int * const foo = ...; // Pointer cannot change, pointed to value can change
const int * bar = ...; // Pointer can change, pointed to value cannot change
int * baz = ...; // Pointer can change, pointed to value can change
const int * const qux = ...; // Pointer cannot change, pointed to value cannot change

6
आप शायद नियम का उपयोग करने के लिए बेहतर हैं "जो कुछ भी बचा है वह कब्ज बनाता है"। जैसे "int * const foo" पॉइंटर को "const" बनाता है, क्योंकि पॉइंटर इसके लिए बचा हुआ है। हालाँकि, आप दूसरी पंक्ति "int const * बार" लिखेंगे, int const बनाता है, क्योंकि यह इसके लिए बचा हुआ है। "int const * const * qux", दोनों को, int और पॉइंटर कोस्ट बनाता है, क्योंकि या तो एक बार इसे छोड़ दिया जाता है।
मखी

4

वे समान हैं, लेकिन C ++ में हमेशा दाईं ओर कास्ट का उपयोग करने का एक अच्छा कारण है। आप सभी जगह सुसंगत रहेंगे क्योंकि कॉन्स्ट मेंबर के कार्यों को इस तरह घोषित किया जाना चाहिए:

int getInt() const;

यह thisफ़ंक्शन में पॉइंटर को से बदल देता Foo * constहै Foo const * constयहाँ देखें।


3
यह पूरी तरह से अलग तरह का कास्ट है।
जस्टिन मेयर्स

1
यह पूरी तरह से अलग क्यों है? नीचे कमाने के लिए पर्याप्त अलग।
निक वेस्टगेट

1
हां, सवाल "कॉन्स्टेंट इंट" और "इंट कॉन्स्ट" के बीच अंतर के बारे में है, आपके जवाब का इससे कोई लेना-देना नहीं है।
जस्टिन मेयर्स

1
मैंने कहा वे वही हैं। और फिर भी स्वीकृत और शीर्ष मतदान जवाब भी सूचक प्रकारों पर अतिरिक्त जानकारी देते हैं। क्या आपने उन लोगों को भी पदच्युत किया?
निक वेस्टगेट


3

मुझे लगता है कि इस मामले में वे समान हैं, लेकिन यहां एक उदाहरण है जहां आदेश मायने रखता है:

const int* cantChangeTheData;
int* const cantChangeTheAddress;

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