सूचक घोषणाओं में तारांकन का स्थान


92

मैंने हाल ही में फैसला किया है कि मुझे बस अंत में C / C ++ सीखना है, और एक बात यह है कि मैं वास्तव में संकेत या अधिक सटीक, उनकी परिभाषा के बारे में नहीं समझता हूं।

इन उदाहरणों के बारे में कैसे:

  1. int* test;
  2. int *test;
  3. int * test;
  4. int* test,test2;
  5. int *test,test2;
  6. int * test,test2;

अब, मेरी समझ से, पहले तीन मामले सभी एक ही कर रहे हैं: टेस्ट एक इंट नहीं, बल्कि एक सूचक है।

उदाहरणों का दूसरा सेट थोड़ा और मुश्किल है। मामले 4 में, टेस्ट और टेस्ट 2 दोनों एक इंट के लिए संकेत होंगे, जबकि 5 के मामले में, केवल टेस्ट एक पॉइंटर है, जबकि टेस्ट 2 एक "वास्तविक" इंट है। केस 6 के बारे में क्या? केस 5 के समान?


9
C / C ++ में सफेद स्थान अर्थ नहीं बदलते हैं।
सुल्तान

18
7. int*test;?
जिन क्वॉन

3
+1 क्योंकि मैंने केवल 1 के बारे में पूछना चाहा था। 3. इस प्रश्न को पढ़कर मुझे 4 - 6 के बारे में कुछ सिखाया गया था जिसके बारे में मैंने कभी नहीं सोचा था।
विनीलसुपरफिरोमैन

@ सुल्तान उस समय के 99% सच है, लेकिन हमेशा नहीं। मेरे सिर के ऊपरी भाग में टेम्प्लेटेड टाइप स्पेस आवश्यकता (पहले C ++ 11) में टेम्पल टाइप का प्रकार था। में लिखा जाता था , ताकि एक सही बदलाव के रूप में इलाज किया जा करने के लिए नहीं। Foo<Bar<char>>>>> >
AnorZaken

3
@AnorZaken आप सही हैं, यह एक पुरानी टिप्पणी है। ऐसी कई स्थितियां हैं जब कोई स्थान अर्थ बदल जाएगा, उदाहरण के लिए, वेतन वृद्धि ++ऑपरेटर को एक स्थान से विभाजित नहीं किया जा सकता है, पहचानकर्ताओं को एक स्थान से विभाजित नहीं किया जा सकता है (और परिणाम अभी भी संकलक के लिए कानूनी हो सकता है लेकिन अपरिभाषित रनटाइम व्यवहार के साथ)। C / C ++ जो सिंटैक्स गड़बड़ है, उसे देखते हुए सटीक स्थितियों को परिभाषित करना बहुत मुश्किल है।
सुल्तान

जवाबों:


129

4, 5 और 6 एक ही चीज हैं, केवल टेस्ट एक पॉइंटर है। यदि आप दो पॉइंटर्स चाहते हैं, तो आपको उपयोग करना चाहिए:

int *test, *test2;

या, और भी बेहतर (सब कुछ स्पष्ट करने के लिए):

int* test;
int* test2;

3
तो केस 4 वास्तव में मौत का जाल है? क्या कोई विनिर्देश या आगे पढ़ने वाला यह बताता है कि int * test, test2 केवल पहले चर को सूचक क्यों बनाता है?
माइकल Stum

8
@ माइकल स्टम इट सी C ++ तो क्या आपको वास्तव में लगता है कि कोई तार्किक व्याख्या है?
जो फिलिप्स

6
K & R (C प्रोग्रामिंग लैंग्वेज) पढ़ें। यह सब बहुत स्पष्ट रूप से समझाता है।
फेर्रुकियो

8
मामले 4, 5 और 6 "डेथ-ट्रैप" हैं। यह एक कारण है कि कई C / C ++ शैली वाले प्रति कथन केवल एक घोषणा का सुझाव देते हैं।
माइकल बूर

14
व्हॉट्सएप सी कंपाइलर (प्रीप्रोसेसर की अनदेखी) के लिए महत्वहीन है। कोई फर्क नहीं पड़ता कि वहाँ कितने रिक्त स्थान हैं या तारांकन और उसके परिवेश के बीच नहीं हैं, इसका बिल्कुल वही अर्थ है।
ephemient

44

तारांकन के आसपास की सफेद जगह का कोई महत्व नहीं है। तीनों का मतलब एक ही है:

int* test;
int *test;
int * test;

" int *var1, var2" एक दुष्ट वाक्य रचना है जो सिर्फ लोगों को भ्रमित करने के लिए है और इसे टाला जाना चाहिए। इसका विस्तार होता है:

int *var1;
int var2;

15
मत भूलना int*test
मतीन उल्हाक '’

1
तारांकन से पहले या बाद का स्थान केवल सौंदर्यशास्त्र की बात है। हालाँकि, Google कोडिंग मानक int *test( google-styleguide.googlecode.com/svn/trunk/… ) के साथ जाता है । बस संगत

@SebastianRaschka Google C ++ स्टाइल गाइड स्पष्ट रूप से या तो तारांकन प्लेसमेंट की अनुमति देता है। जब से आपने इसे पढ़ा है शायद यह बदल गया है।
जैरेड बेक

33

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


थोड़ा अलग मुझे पता है, लेकिन मुझे जो कुछ उपयोगी लगा वह है पीछे की घोषणाओं को पढ़ना।

int* test;   // test is a pointer to an int

यह बहुत अच्छी तरह से काम करना शुरू कर देता है, खासकर जब आप कॉन्स्टेंट पॉइंटर्स की घोषणा करना शुरू करते हैं और यह जानने के लिए मुश्किल हो जाता है कि क्या यह पॉइंटर है जो कॉन्स है, या इसकी बात यह है कि पॉइंटर उस तरफ इशारा कर रहा है।

int* const test; // test is a const pointer to an int

int const * test; // test is a pointer to a const int ... but many people write this as  
const int * test; // test is a pointer to an int that's const

जबकि "एक चर प्रति पंक्ति" उपयोगी लगता है, हमने अभी भी उस स्थिति को पूरी तरह से हल नहीं किया है जहां तारांकन बाईं ओर अधिक है, या दाईं ओर अधिक है। मुझे पूरा यकीन है कि वाइल्ड में कोड आउट में एक वेरिएंट रहता है; कुछ देशों की तरह कुछ दाईं ओर ड्राइव करते हैं, और अन्य गलत दिशा में ड्राइव करते हैं, जैसे कि यूके। ;-)
शेवी

दुर्भाग्य से मेरे कारनामों से लेकर जंगली तक दोनों शैलियों को खूब देखता हूं। मेरी टीम में अब हम एक शैली के साथ क्लैंग-प्रारूप का उपयोग करते हैं, जिस पर हम सहमत हुए हैं। कम से कम इसका मतलब है कि हमारी टीम द्वारा निर्मित सभी कोड में वही शैली है जहां व्हॉट्सएप जाता है।
स्कॉट लंघम

33

पार्स सी / सी ++ घोषणाओं में मदद करने के लिए "क्लॉकवाइज सर्पिल नियम" का उपयोग करें ;

पालन ​​करने के लिए तीन सरल चरण हैं:

  1. अज्ञात तत्व के साथ शुरू, एक सर्पिल / घड़ी की दिशा में आगे बढ़ें; निम्नलिखित तत्वों का सामना करते समय उन्हें संबंधित अंग्रेजी बयानों से बदल दें:

    [X]या []: एरे एक्स आकार का ... या एरे अपरिभाषित आकार ...

    (type1, type2): फ़ंक्शन पासिंग टाइप 1 और टाइप 2 रिटर्निंग ...

    *: सूचक (ओं) को ...

  2. इसे एक सर्पिल / घड़ी की दिशा में तब तक करते रहें जब तक कि सभी टोकन कवर न हो जाएं।
  3. कोष्ठक में हमेशा कुछ भी हल करें!

इसके अलावा, घोषणाएं अलग-अलग बयानों में हो सकती हैं जब संभव हो (जो कि अधिकांश समय सच है)।


4
यह कहने के लिए खेदजनक और भयानक लग रहा है।
जो फिलिप्स

7
यह होता है, लेकिन इसे और अधिक जटिल निर्माणों में से कुछ के लिए काफी अच्छा स्पष्टीकरण लगता है
माइकल Stum

@ d03boy: कोई सवाल नहीं है - सी / सी ++ घोषणाएं एक बुरा सपना हो सकती हैं।
माइकल बूर

2
"सर्पिल" कोई मतलब नहीं है, बहुत कम "दक्षिणावर्त"। बल्कि मैं इसे "राइट-लेफ्ट रूल" नाम दूंगा, क्योंकि सिंटैक्स आपको राइट-लेफ्ट-टॉप नहीं दिखता, केवल राइट-लेफ्ट।
रुस्लान

मैंने इसे "दाएं-बाएं-दाएं" नियम के रूप में सीखा। C ++ के लोग अक्सर सभी प्रकार की सूचनाओं का दिखावा करना पसंद करते हैं जो बाईं ओर है, जो int* x;पारंपरिक int *x;शैली के बजाय शैली की ओर जाता है । बेशक, रिक्ति कंपाइलर के लिए मायने नहीं रखती है, लेकिन यह मनुष्यों को प्रभावित करती है। वास्तविक वाक्य रचना का खंडन शैली नियमों की ओर जाता है जो पाठकों को परेशान और भ्रमित कर सकते हैं।
एड्रियन मैक्कार्थी

12

जैसा कि दूसरों ने उल्लेख किया है, 4, 5 और 6 समान हैं। अक्सर, लोग इन उदाहरणों का उपयोग इस तर्क को करने के लिए करते हैं कि *प्रकार के बजाय चर के साथ संबंधित है। हालांकि यह शैली का मुद्दा है, इस पर कुछ बहस है कि क्या आपको इस तरह से सोचना और लिखना चाहिए:

int* x; // "x is a pointer to int"

या इस तरह:

int *x; // "*x is an int"

FWIW मैं पहले कैंप में हूं, लेकिन इसका कारण यह है कि दूसरे लोग दूसरे फॉर्म के लिए तर्क देते हैं कि यह (ज्यादातर) इस विशेष प्रश्न को हल करता है:

int* x,y; // "x is a pointer to int, y is an int"

जो संभावित रूप से भ्रामक है; इसके बजाय आप या तो लिखेंगे

int *x,y; // it's a little clearer what is going on here

या यदि आप वास्तव में दो संकेत चाहते हैं,

int *x, *y; // two pointers

व्यक्तिगत रूप से, मैं कहता हूं कि इसे प्रति पंक्ति एक चर में रखें, फिर इससे कोई फर्क नहीं पड़ता कि आप किस शैली को पसंद करते हैं।


6
यह फर्जी है, आप क्या कहते हैं int *MyFunc(void)? एक *MyFuncएक समारोह में लौट रहा है int? नहीं। जाहिर है कि हमें लिखना चाहिए int* MyFunc(void), और कहना चाहिए कि MyFuncएक समारोह एक लौट रहा है int*। तो मेरे लिए यह स्पष्ट है, C और C ++ व्याकरण पार्सिंग नियम केवल चर घोषणा के लिए गलत हैं। उन्हें संपूर्ण अल्पविराम अनुक्रम के लिए साझा प्रकार के हिस्से के रूप में सूचक योग्यता शामिल होनी चाहिए।
v.oddou

1
लेकिन *MyFunc() है एक int। C सिंटैक्स के साथ समस्या प्रीफ़िक्स और पोस्टफ़िक्स सिंटैक्स को मिला रही है - यदि केवल पोस्टफ़िक्स का उपयोग किया गया था, तो कोई भ्रम नहीं होगा।
एंटटी हापाला

1
पहला शिविर भाषा की वाक्य रचना से लड़ता है, जिससे भ्रमित निर्माण जैसे होते हैं int const* x;, जो मुझे भ्रामक लगता है a * x+b * y
एड्रियन मैक्कार्थी


5

4, 5 और 6 में, testहमेशा पॉइंटर होता है और पॉइंटर test2नहीं होता है। श्वेत स्थान C ++ में कभी महत्वपूर्ण नहीं है।


3

मेरी राय में, स्थिति के आधार पर, उत्तर दोनों है। आम तौर पर, IMO, सूचक नाम के आगे तारांकन चिह्न रखना बेहतर होता है, बजाय टाइप के। उदाहरण की तुलना करें:

int *pointer1, *pointer2; // Fully consistent, two pointers
int* pointer1, pointer2;  // Inconsistent -- because only the first one is a pointer, the second one is an int variable
// The second case is unexpected, and thus prone to errors

दूसरा मामला असंगत क्यों है? क्योंकि उदा int x,y;एक ही प्रकार के दो चर घोषित करता है लेकिन घोषणा में केवल एक बार ही इस प्रकार का उल्लेख किया जाता है। यह एक मिसाल और अपेक्षित व्यवहार बनाता है। और int* pointer1, pointer2;इसके साथ असंगत है क्योंकि यह pointer1एक संकेतक के रूप में घोषित करता है, लेकिन pointer2एक पूर्णांक चर है। स्पष्ट रूप से त्रुटियों की संभावना है और, इस प्रकार, (टाइपकर्ता के बजाय सूचक नाम के बगल में तारांकन करके) टाला जाना चाहिए।

हालांकि , कुछ अपवाद हैं जहां आप ऑब्जेक्ट नाम के आगे तारांकन चिह्न नहीं लगा सकते हैं (और जहां आप इसे डालते हैं, वहां कोई फर्क नहीं पड़ता) अवांछित परिणाम प्राप्त किए बिना - उदाहरण के लिए:

MyClass *volatile MyObjName

void test (const char *const p) // const value pointed to by a const pointer

अंत में, कुछ मामलों में, टाइप नाम के आगे तारांकन चिह्न लगाने के लिए यह स्पष्ट रूप से स्पष्ट हो सकता है , उदाहरण के लिए:

void* ClassName::getItemPtr () {return &item;} // Clear at first sight


2

C में तर्क यह है कि आप चर का उपयोग करने के तरीके को घोषित करते हैं। उदाहरण के लिए

char *a[100];

कहता है कि *a[42]एक हो जाएगा char। और a[42]एक चर सूचक। और इस प्रकार aचार बिंदुओं की एक सरणी है।

ऐसा इसलिए है क्योंकि मूल संकलक लेखक अभिव्यक्ति और घोषणाओं के लिए एक ही पार्सर का उपयोग करना चाहते थे। (लैंगेज डिजाइन पसंद के लिए बहुत समझदार कारण नहीं)


फिर भी लेखन char* a[100]; यह भी कहता है कि *a[42];एक charऔर a[42];एक चार सूचक होगा।
यनी

खैर, हम सभी एक ही निष्कर्ष निकालते हैं, केवल क्रम अलग-अलग होता है।
मिशेल बिल्लौद

उद्धरण: "यह कहता है कि * एक [42] एक चार होगा। और एक [42] एक चार सूचक"। क्या आप सुनिश्चित हैं कि यह दूसरा तरीका नहीं है?
deLock

यदि आप दूसरे तरीके को पसंद करते हैं, तो कहना a[42]एक charसंकेतक है, और *a[42]एक चर है।
मिशेल बिल्लौद

2

मैं कहूंगा कि शुरुआती सम्मेलन में स्टार को सूचक नाम की ओर (घोषणा के दाईं ओर) रखा गया था

  • में सी प्रोग्रामिंग भाषा डेनिस एम रिची द्वारा सितारों घोषणा के दाईं ओर कर रहे हैं।

  • https://github.com/torvalds/linux/blob/master/init/main.c पर लिनक्स सोर्स कोड को देखकर हम देख सकते हैं कि तारा दाईं ओर भी है।

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


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

1

सूचक प्रकार का एक संशोधक है। यह समझना बेहतर है कि तारांकन किस प्रकार को संशोधित करता है, इसे बेहतर ढंग से समझने के लिए उन्हें बाएं से दाएं पढ़ना चाहिए। 'int *' को "pointer to int 'के रूप में पढ़ा जा सकता है। कई घोषणाओं में आपको यह बताना होगा कि प्रत्येक चर एक सूचक है या इसे एक मानक चर के रूप में बनाया जाएगा।

1,2 और 3) टेस्ट टाइप (int *) का है। व्हॉट्सएप कोई मायने नहीं रखता।

4,5 और 6) टेस्ट टाइप (int *) का है। Test2 टाइप इंट का है। फिर से व्हाट्सएप अयोग्य है।


-3

अंगूठे का एक अच्छा नियम, बहुत से लोग इन अवधारणाओं को समझ लेते हैं: C ++ में बहुत अधिक अर्थ का अर्थ कीवर्ड या पहचानकर्ताओं के बाएं-बंधन से होता है।

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

int const bla;

कॉन्स्ट "इंट" शब्द पर लागू होता है। पॉइंटर्स के तारांकन के साथ भी यही है, वे उनके द्वारा छोड़े गए कीवर्ड पर लागू होते हैं। और वास्तविक चर नाम? हाँ, यह क्या है इसके द्वारा घोषित किया गया है।


1
इस सवाल का जवाब नहीं है। इससे भी बदतर, अगर हम इसमें से एक उत्तर का अनुमान लगाने की कोशिश करते हैं , तो इसका मतलब यह है कि तारांकन चिह्न इसके बाईं ओर के प्रकार के हैं, जो कि बाकी सभी ने कहा है कि यह गलत है। यह एकल चर नाम को इसके दाईं ओर बांधता है।
अंडरस्कोर_ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.