C ++ पहचानकर्ता में अंडरस्कोर का उपयोग करने के बारे में क्या नियम हैं?


930

स्थानीय चर या मापदंडों के बजाय इस तथ्य को निरूपित करने के लिए कि किसी प्रकार के उपसर्ग के साथ सदस्य चर का नाम देना C ++ में आम है। यदि आप MFC बैकग्राउंड से आते हैं, तो आप शायद इस्तेमाल करेंगे m_foo। मैंने भी myFooकभी-कभी देखा है ।

C # (या संभवतः सिर्फ .NET) के रूप में सिर्फ एक अंडरस्कोर का उपयोग करने की सलाह देता है _foo। क्या यह C ++ मानक द्वारा अनुमत है?


3
इसके बारे में glibc मैनुअल पेज gnu.org/software/libc/manual/html_node/Reserved-Names.html पर पाया जा सकता है। संपादित करें: यह भी देखें कि opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html
CesarB

6
बस ध्यान दें कि इन नियमों की अज्ञानता का मतलब यह नहीं है कि आपका कोड संकलित या चलेगा नहीं, लेकिन संभावना है कि आपका कोड अलग-अलग संकलक और संस्करण में पोर्टेबल नहीं होगा, क्योंकि यह गारंटी नहीं दी जा सकती है कि नाम नहीं होगा झड़प। इसे वापस करने के लिए मुझे एक महत्वपूर्ण प्रणाली के निश्चित कार्यान्वयन के बारे में पता है जो हर जगह नामकरण सम्मेलन _ पूंजी पत्र के रूप में उपयोग कर रहा है। जहां इसके कारण कोई त्रुटि नहीं है। बेशक यह बुरा अभ्यास है।
g24l

जवाबों:


851

नियम (जो C ++ 11 में नहीं बदले गए):

  • कार्यान्वयन मैक्रो के रूप में उपयोग के लिए सहित किसी भी दायरे में आरक्षित :
    • एक अपरकेस के साथ शुरुआत करने वाले पहचानकर्ता तुरंत एक बड़े अक्षर के बाद आते हैं
    • समीपवर्ती अंडरस्कोर (या "डबल अंडरस्कोर") वाले पहचानकर्ता
  • वैश्विक नाम स्थान में आरक्षित:
    • एक अंडरस्कोर के साथ शुरुआत करने वाले पहचानकर्ता
  • इसके अलावा, stdनाम स्थान में सब कुछ आरक्षित है। (आपको टेम्पलेट विशेषज्ञताओं को जोड़ने की अनुमति है, हालांकि)

2003 C ++ मानक से:

17.4.3.1.2 वैश्विक नाम [lib.global.names]

नाम और फ़ंक्शन हस्ताक्षरों के कुछ सेट हमेशा कार्यान्वयन के लिए आरक्षित होते हैं:

  • प्रत्येक नाम जिसमें एक डबल अंडरस्कोर ( __) है या एक अपरकेस अक्षर के साथ शुरू होता है (2.11) किसी भी उपयोग के लिए कार्यान्वयन के लिए आरक्षित है।
  • अंडरस्कोर से शुरू होने वाला प्रत्येक नाम वैश्विक नामस्थान में एक नाम के रूप में उपयोग के लिए कार्यान्वयन के लिए आरक्षित है। 165

165) ऐसे नाम नेमस्पेस ::std(17.4.3.1) में भी आरक्षित हैं ।

क्योंकि C ++ C मानक (1.1 / 2, C ++ 03) पर आधारित है और C99 एक मानक संदर्भ है (1.2 / 1, C ++ 03) ये भी लागू होते हैं, 1999 C मानक से:

7.1.3 आरक्षित पहचानकर्ता

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

  • सभी पहचानकर्ता जो एक अंडरस्कोर के साथ शुरू होते हैं और या तो एक बड़े अक्षर या किसी अन्य अंडरस्कोर हमेशा किसी भी उपयोग के लिए आरक्षित होते हैं।
  • सभी पहचानकर्ता जो एक अंडरस्कोर से शुरू होते हैं, हमेशा साधारण और टैग नाम स्थान दोनों में फ़ाइल स्कोप वाले पहचानकर्ताओं के रूप में उपयोग के लिए आरक्षित होते हैं।
  • निम्न उपवर्गों में से प्रत्येक में एक स्थूल नाम (भविष्य की लाइब्रेरी दिशाओं सहित) निर्दिष्ट के रूप में उपयोग के लिए आरक्षित है यदि इसके किसी भी संबंधित हेडर को शामिल किया गया है; जब तक स्पष्ट रूप से अन्यथा न कहा जाए (देखें 7.1.4)।
  • निम्नलिखित उपवर्गों में से किसी में बाहरी लिंकेज वाले सभी पहचानकर्ता (भविष्य की लाइब्रेरी दिशाओं सहित) हमेशा बाहरी लिंकेज वाले पहचानकर्ताओं के रूप में उपयोग के लिए आरक्षित होते हैं। 154
  • निम्न उपवर्गों में से किसी में सूचीबद्ध फ़ाइल स्कोप वाले प्रत्येक पहचानकर्ता (भविष्य की लाइब्रेरी दिशाओं सहित) को मैक्रो नाम के रूप में उपयोग करने के लिए आरक्षित किया गया है और यदि किसी भी संबंधित हेडर को शामिल किया गया है तो उसी नाम स्पेस में फ़ाइल स्कोप के साथ एक पहचानकर्ता के रूप में।

कोई अन्य पहचानकर्ता आरक्षित नहीं है। यदि कार्यक्रम एक ऐसे संदर्भ में पहचानकर्ता की घोषणा या परिभाषित करता है जिसमें यह आरक्षित है (7.1.4 द्वारा अनुमत के अलावा), या एक स्थूल नाम के रूप में आरक्षित पहचानकर्ता को परिभाषित करता है, तो व्यवहार अपरिभाषित है।

यदि प्रोग्राम #undefऊपर सूचीबद्ध पहले समूह में एक पहचानकर्ता की किसी भी स्थूल परिभाषा को हटा देता है (के साथ ), व्यवहार अपरिभाषित है।

154) बाहरी लिंकेज के साथ सुरक्षित पहचानकर्ता के सूची में शामिल हैं errno, math_errhandling, setjmp, और va_end

अन्य प्रतिबंध लागू हो सकते हैं। उदाहरण के लिए, POSIX मानक में बहुत सारे पहचानकर्ता होते हैं जो सामान्य कोड में दिखाई देते हैं:

  • एक पूंजी के साथ शुरू होने वाले नामों Eने एक अंक या बड़े अक्षर का अनुसरण किया:
    • अतिरिक्त त्रुटि कोड नामों के लिए उपयोग किया जा सकता है।
  • नाम जो isया तो toलोअरकेस अक्षर से शुरू होते हैं
    • अतिरिक्त चरित्र परीक्षण और रूपांतरण कार्यों के लिए उपयोग किया जा सकता है।
  • नाम जो LC_एक बड़े अक्षर से शुरू होते हैं
    • स्थानीय विशेषताओं को निर्दिष्ट करने वाले अतिरिक्त मैक्रो के लिए उपयोग किया जा सकता है।
  • सभी मौजूदा गणित कार्यों के नाम के साथ प्रत्यय fया lआरक्षित हैं
    • इसी कार्यों के लिए जो क्रमशः फ्लोट और लंबे डबल तर्कों पर काम करते हैं।
  • SIGएक बड़े अक्षर के बाद शुरू होने वाले नाम आरक्षित हैं
    • अतिरिक्त संकेत नामों के लिए।
  • SIG_एक बड़े अक्षर के बाद शुरू होने वाले नाम आरक्षित हैं
    • अतिरिक्त सिग्नल कार्यों के लिए।
  • के साथ शुरुआत नाम str, memया wcsएक छोटा अक्षर के बाद आरक्षित हैं
    • अतिरिक्त स्ट्रिंग और सरणी फ़ंक्शन के लिए।
  • किसी लोअरकेस अक्षर के साथ PRIया SCNउसके बाद शुरू होने वाले नाम या Xआरक्षित हैं
    • अतिरिक्त प्रारूप निर्दिष्ट मैक्रोज़ के लिए
  • जो नाम समाप्त होते _tहैं, वे आरक्षित होते हैं
    • अतिरिक्त प्रकार के नामों के लिए।

अपने स्वयं के प्रयोजनों के लिए इन नामों का उपयोग करते समय अभी समस्या पैदा नहीं हो सकती है, वे उस मानक के भविष्य के संस्करणों के साथ संघर्ष की संभावना को बढ़ाते हैं।


व्यक्तिगत रूप से मैं सिर्फ अंडरस्कोर वाले पहचानकर्ताओं को शुरू नहीं करता हूं। मेरे नियम के अलावा नया: कहीं भी डबल अंडरस्कोर का उपयोग न करें, जो आसान है क्योंकि मैं शायद ही कभी अंडरस्कोर का उपयोग करता हूं।

इस लेख पर शोध करने के बाद मैं अपने पहचानकर्ताओं को समाप्त नहीं करता _t क्योंकि यह POSIX मानक द्वारा आरक्षित है।

किसी भी पहचानकर्ता के समाप्त होने के बारे में नियम ने _tमुझे बहुत आश्चर्यचकित किया। मुझे लगता है कि स्पष्टीकरण और आधिकारिक अध्याय और पद्य की तलाश में यह एक POSIX मानक है (अभी तक निश्चित नहीं है)। यह जीएनयू लिबटूल मैनुअल से है , आरक्षित नामों को सूचीबद्ध करता है।

CesarB ने POSIX 2004 आरक्षित प्रतीकों और नोटों के लिए निम्न लिंक प्रदान किया है 'कई अन्य आरक्षित उपसर्गों और प्रत्ययों ... वहाँ पाया जा सकता है'। POSIX 2008 सुरक्षित प्रतीकों यहाँ परिभाषित कर रहे हैं। प्रतिबंध कुछ हद तक ऊपर की तुलना में अति सूक्ष्म हैं।


14
C ++ मानक C को "इम्पोर्ट" नहीं करता है, क्या यह करता है? वे कुछ हेडर आयात करते हैं, लेकिन पूरे नियम या नामकरण नियमों के रूप में नहीं, जहां तक ​​मुझे पता है। लेकिन हाँ, _t ने मुझे भी हैरान कर दिया। लेकिन चूंकि यह सी है, यह केवल वैश्विक एनएस पर लागू हो सकता है। वर्गों के अंदर _t का उपयोग करने के लिए सुरक्षित होना चाहिए क्योंकि मैंने इसे पढ़ा है
jalf

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

8
यह वही है जो मैंने "_t" मुद्दे के बारे में पाया है: n1256 (C99 TC3) कहता है: "टाइप किए गए नाम int या uint से शुरू होते हैं और _t के साथ समाप्त होते हैं" आरक्षित हैं। मुझे लगता है कि अभी भी "foo_t" जैसे नामों का उपयोग करने की अनुमति देता है - लेकिन मुझे लगता है कि ये POSIX द्वारा आरक्षित हैं।
जोहान्स स्काउब -

59
इसलिए 'सहिष्णुता' POSIX द्वारा आरक्षित है क्योंकि यह 'से' के साथ शुरू होता है + एक निचला अक्षर? मैं शर्त लगाता हूँ कि बहुत सारे कोड इस नियम को तोड़ते हैं!
Sjoerd

23
@ लोकीअस्टारी, " C ++ मानक C मानक के संदर्भ में परिभाषित किया गया है। मूल रूप से यह कहता है कि C ++ इन अंतर और परिवर्धन के साथ C है। " बकवास! C ++ केवल C मानक को [basic.fundamental] और लाइब्रेरी में संदर्भित करता है। यदि आप जो कहते हैं वह सच है, तो C ++ कहाँ कहता है _Boolऔर _ImaginaryC ++ में मौजूद नहीं है? C ++ भाषा को स्पष्ट रूप से परिभाषित किया गया है, C को "संपादन" के संदर्भ में नहीं, अन्यथा मानक बहुत छोटा हो सकता है!
जोनाथन वेकली

197

नामों की टकराहट से बचने के नियम C ++ मानक (Stroustrup पुस्तक देखें) और C ++ गुरु (सटर, आदि) द्वारा उल्लिखित दोनों हैं।

व्यक्तिगत नियम

क्योंकि मैं मामलों से निपटना नहीं चाहता था, और एक सरल नियम चाहता था, मैंने एक व्यक्तिगत डिजाइन किया है जो सरल और सही दोनों है:

जब एक प्रतीक का नामकरण, आप संकलक / ओएस / मानक पुस्तकालयों के साथ टकराव से बचेंगे यदि आप:

  • एक अंडरस्कोर के साथ एक प्रतीक शुरू कभी न करें
  • कभी भी अंदर के दो अंडरस्कोर वाले सिंबल का नाम न लें।

बेशक, अपने कोड को एक अद्वितीय नामस्थान में रखने से टकराव से बचने में मदद मिलती है, (लेकिन यह बुरे मैक्रो से रक्षा नहीं करेगा)

कुछ उदाहरण

(मैं मैक्रोज़ का उपयोग करता हूं क्योंकि वे C / C ++ प्रतीकों के अधिक कोड-प्रदूषण हैं, लेकिन यह चर नाम से लेकर कक्षा तक कुछ भी हो सकता है)

#define _WRONG
#define __WRONG_AGAIN
#define RIGHT_
#define WRONG__WRONG
#define RIGHT_RIGHT
#define RIGHT_x_RIGHT

C ++ 0x ड्राफ्ट से अर्क

से n3242.pdf फ़ाइल (मैं समान होने के लिए अंतिम मानक पाठ की उम्मीद):

17.6.3.3.2 वैश्विक नाम [global.names]

नाम और फ़ंक्शन हस्ताक्षरों के कुछ सेट हमेशा कार्यान्वयन के लिए आरक्षित होते हैं:

- प्रत्येक नाम जिसमें एक डबल अंडरस्कोर _ _ है या एक अंडरस्कोर के साथ शुरू होता है उसके बाद एक अपरकेस अक्षर (2.12) किसी भी उपयोग के लिए कार्यान्वयन के लिए आरक्षित है।

- प्रत्येक नाम जो एक अंडरस्कोर से शुरू होता है, वैश्विक नामस्थान में एक नाम के रूप में उपयोग के लिए कार्यान्वयन के लिए आरक्षित है।

लेकिन:

17.6.3.3.5 उपयोगकर्ता द्वारा परिभाषित शाब्दिक प्रत्यय [usrlit.suffix]

शाब्दिक प्रत्यय पहचानकर्ता जो अंडरस्कोर से शुरू नहीं होते हैं, भविष्य के मानकीकरण के लिए आरक्षित हैं।

यह अंतिम खंड भ्रमित करने वाला है, जब तक आप विचार नहीं करते हैं कि एक नाम एक अंडरस्कोर से शुरू होता है और उसके बाद एक लोअरकेस अक्षर ठीक होता है यदि वैश्विक नामस्थान में परिभाषित नहीं किया गया है ...


9
@ मायसम: __WRONG_AGAIN__लगातार दो अंडरस्कोर (शुरुआत में दो और अंत में दो) होते हैं, इसलिए यह मानक के अनुसार गलत है।
पियरसबल

8
@ B @овиЈ: WRONG__WRONGदो लगातार अंडरस्कोर (बीच में दो) शामिल हैं, इसलिए यह मानक के अनुसार गलत है
पेरेसबल

2
अपने कोड को एक अद्वितीय नामस्थान में रखने से टकराव से बचने में मदद मिलती है : लेकिन यह अभी भी पर्याप्त नहीं है, क्योंकि पहचानकर्ता किसी कीवर्ड से टकरा सकता है, भले ही गुंजाइश के बिना (जैसे __attribute__जीसीसी के लिए)।
रुस्लान

1
मानक के अनुसार मध्य में लगातार दो अंडरस्कोर होने की कोई समस्या क्यों है ? उपयोगकर्ता-परिभाषित शाब्दिक प्रत्यय जैसे 1234567Lया शाब्दिक मूल्यों पर लागू होते हैं 4.0f; IIRC यह ओहटप को संदर्भित करता है: //en.cppreference.com/w/cpp/language/user_literal
जेसन एस

1
Why is there any problem of having two consecutive underscores in the middle according to the standard?क्योंकि मानक कहते हैं कि आरक्षित हैं। यह अच्छी या बुरी शैली पर एक सलाह नहीं है। यह मानक से निर्णय है। उन्होंने यह फैसला क्यों किया? मुझे लगता है कि पहले संकलक पहले से ही मानकीकरण से पहले अनौपचारिक रूप से इस तरह के सम्मेलनों का इस्तेमाल करते थे।
पियरसबल

38

से MSDN :

एक पहचानकर्ता की शुरुआत में दो अनुक्रमिक अंडरस्कोर वर्ण (__) का उपयोग, या एक बड़े अक्षर के बाद एक एकल प्रमुख अंडरस्कोर, सभी स्कैप में C ++ कार्यान्वयन के लिए आरक्षित है। आपको वर्तमान या भविष्य के अन्य पहचानकर्ताओं के साथ संभावित संघर्षों के कारण फ़ाइल स्कोप वाले नामों के लिए निचले अक्षर के बाद एक प्रमुख अंडरस्कोर का उपयोग करने से बचना चाहिए।

इसका मतलब है कि आप एक एकल अंडरस्कोर का उपयोग एक सदस्य चर उपसर्ग के रूप में कर सकते हैं, जब तक कि यह निम्न-केस पत्र द्वारा पीछा किया जाता है।

यह जाहिरा तौर पर C ++ मानक के खंड 17.4.3.1.2 से लिया गया है, लेकिन मुझे पूर्ण मानक ऑनलाइन के लिए एक मूल स्रोत नहीं मिल सकता है।

यह प्रश्न भी देखें ।


2
मुझे अनुभाग में n3092.pdf (C ++ 0x मानक का मसौदा) में इसी तरह का एक पाठ मिला: "17.6.3.3.2 वैश्विक नाम"
पियरसेबल

7
मजे की बात यह है कि यह एकमात्र ऐसा उत्तर है, जिसमें प्रश्न का प्रत्यक्ष, संक्षिप्त उत्तर है।
हाइड

9
@ लिप: वास्तव में, यह नहीं है, क्योंकि यह नियम है कि वैश्विक नामों में अग्रणी अंडरस्कोर के साथ किसी भी पहचानकर्ता नहीं होना चाहिए। देखें रोजर के जवाब । मैं C ++ मानक पर एक प्राधिकरण के रूप में MS VC डॉक्स के उद्धरणों से बहुत सावधान रहूंगा।
sbi

@sbi मैं "आप एक एकल अंडरस्कोर का उपयोग एक सदस्य चर उपसर्ग के रूप में कर सकते हैं, जब तक कि यह एक निम्न-केस पत्र द्वारा पीछा किया जाता है" इस उत्तर में, जो प्रश्न पाठ पर प्रश्न का उत्तर सीधे और संक्षेप में, बिना डूबा जा रहा है। पाठ की एक दीवार में।
हाइड

5
सबसे पहले, मैं अभी भी किसी भी संकेत की कमी पर विचार करता हूं कि एक ही नियम वैश्विक नामस्थान विफलता पर लागू नहीं होता है। हालांकि, इससे भी बुरा यह है कि आसन्न अंडरस्कोर न केवल शुरुआत में, बल्कि कहीं भी , एक पहचानकर्ता के लिए मना किया जाता है। तो यह जवाब केवल एक तथ्य को छोड़ नहीं है, लेकिन वास्तव में कम से कम एक सक्रिय रूप से गलत दावा करता है। जैसा कि मैंने कहा, MSVC डॉक्स का जिक्र कुछ ऐसा है जो मैं तब तक नहीं करूंगा जब तक कि प्रश्न केवल वीसी के बारे में ही न हो।
sbi

25

प्रश्न के अन्य भाग के रूप में, यह कुछ भी आंतरिक के साथ संघर्ष नहीं करने के लिए चर नाम के अंत में अंडरस्कोर डालना आम है ।

मैं कक्षाओं और नामस्थानों के अंदर भी ऐसा करता हूं क्योंकि मुझे केवल एक नियम याद रखना पड़ता है (वैश्विक दायरे में नाम के अंत में, और हर जगह नाम की शुरुआत की तुलना में)।


2

हाँ, पहचानकर्ता में कहीं भी अंडरस्कोर का उपयोग किया जा सकता है। मेरा मानना ​​है कि नियम हैं: पहले अक्षर में कोई भी, AZ, _ और निम्न वर्णों के लिए + 0-9।

अंडर कोडकोर उपसर्ग सी कोड में आम हैं - एक एकल अंडरस्कोर का अर्थ "निजी" है, और डबल अंडरस्कोर आमतौर पर कंपाइलर द्वारा उपयोग के लिए आरक्षित हैं।


3
वे पुस्तकालयों में आम हैं। उन्हें उपयोगकर्ता कोड में आम नहीं होना चाहिए।
मार्टिन यॉर्क

43
लोग करते हैं सी में लिखने पुस्तकालयों, तुम्हें पता है।
जॉन मिलिकिन

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