2009-06-30 12 views
5

मैं सी ++ के लिए अपेक्षाकृत नया हूं (अनुभव का लगभग एक वर्ष, चालू और बंद)। मैं type * name के पॉइंटर्स को परिभाषित करने के लिए वाक्यविन्यास के रूप में निर्णय लेने के बारे में उत्सुक हूं। ऐसा लगता है कि वाक्यविन्यास type & name होना चाहिए क्योंकि & प्रतीक को चर के मेमोरी पते के संदर्भ में कोड में हर जगह उपयोग किया जाता है। तो, int संकेत के पारंपरिक उदाहरण उपयोग करने के लिए:पॉइंटर को परिभाषित करते समय हम "टाइप और var" के बजाय "टाइप * var" का उपयोग क्यों करते हैं?

int a = 1; 
int * b = &a; 

int a = 1; 
int & b = &a 

बन जाएगा मैं वहाँ यह है कि मैं सिर्फ दिखाई नहीं दे रहा के लिए किसी कारण है यकीन है, और मैं अच्छा लगेगा सी ++ दिग्गजों से कुछ इनपुट सुनें।

धन्यवाद, एस

+2

"सी/सी ++" मत कहें। सी और सी ++ अलग-अलग भाषाएं हैं। –

+0

इसे बदल दिया, लेकिन पॉइंटर्स दोनों में समान तरीके से काम नहीं करते हैं? – spencewah

+0

सी में संदर्भ नहीं है। –

उत्तर

7

सी ++ सी वाक्यविन्यास को गोद ले। जैसा कि "The Development of the C Language" (डेनिस रिची द्वारा) में खुलासा किया गया है, सी * का उपयोग पॉइंटर्स में टाइप घोषणाओं के लिए करता है क्योंकि यह निर्णय लिया गया था कि टाइप सिंटैक्स का उपयोग करना चाहिए। सूचकांक सरणी, फ़ंक्शन को कॉल करें, सूचक पर अविवेक ऑपरेटर [*] का उपयोग करें:

[एक यौगिक प्रकार] की प्रत्येक वस्तु के लिए, वहाँ पहले से ही एक तरह से अंतर्निहित वस्तु का उल्लेख किया गया था। एनालॉजिकल तर्क ने अभिव्यक्ति वाक्यविन्यास के मिररिंग नामों के लिए एक घोषणा वाक्यविन्यास का नेतृत्व किया जिसमें नाम आम तौर पर दिखाई देते हैं। इस प्रकार,

int i, *pi, **ppi; 

एक पूर्णांक, एक पूर्णांक के लिए सूचक, एक पूर्णांक के लिए सूचक को एक सूचक की घोषणा। इन घोषणाओं का वाक्यविन्यास अवलोकन को दर्शाता है कि मैं, * पीआई, और ** पीपीआई सभी अभिव्यक्ति में उपयोग किए जाने पर एक int प्रकार उत्पन्न करते हैं।

यहाँ एक अधिक जटिल उदाहरण है:

int *(*foo)[4][]; 

इस घोषणा का मतलब है एक अभिव्यक्ति *(*foo)[4][0] टाइप int है, और वह से (और कहा कि [] एकल * की तुलना में अधिक पूर्वता है) आप प्रकार डिकोड कर सकते हैं: foo पॉइंटर्स की सरणी के आकार 4 की सरणी के लिए एक सूचक है।

यह वाक्यविन्यास सी ++ में सी के साथ संगतता के लिए अपनाया गया था। इसके अलावा, यह न भूलें कि सी ++ के पास घोषणाओं में & का उपयोग है।

int & b = a; 

ऊपर लाइन प्रकार int का एक और चर के लिए एक संदर्भ चर चर्चा करते हुए का मतलब है। संदर्भ और सूचक के बीच का अंतर मोटे तौर पर है कि संदर्भ केवल आरंभ किए गए हैं, और आप कहां बदलते हैं, वे बदल नहीं सकते हैं, और आखिर में वे हमेशा स्वचालित रूप से अव्यवस्थित होते हैं। "* ख एक पूर्णांक है":

int x = 5, y = 10; 
int& r = x; 

int sum = r + y; // you do not need to say '*r' automatically dereferenced. 

r = y; // WRONG, 'r' can only have one thing pointing at during its life, only at its infancy ;) 
+0

धन्यवाद, मैं संदर्भ और पॉइंटर्स के बारे में कुछ गलत धारणाएं कर रहा था (मुख्य रूप से वे एक ही हैं, जब वे नहीं हैं)। – spencewah

1

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

दाईं तरफ '&' हमेशा पते का मतलब है। एक परिभाषा में यह इंगित करता है कि चर एक संदर्भ है।

दाईं तरफ '*' हमेशा मूल्य-पर-पता का मतलब है। एक परिभाषा में यह इंगित करता है कि चर एक सूचक है।

संदर्भ और पॉइंटर्स समान हैं, लेकिन समान नहीं हैं। यह article अंतरों को संबोधित करता है।

+0

मुझे नहीं लगता कि दूसरा ब्लॉक * माना * कानूनी कोड होना है - यह एक काल्पनिक उदाहरण है। –

+0

धन्यवाद, आलेख (और संदर्भ और पॉइंटर्स का असंबद्धता) सहायक था। – spencewah

+0

दूसरा उदाहरण मान्य नहीं है और न ही सी ++ में। आप किसी मान के संदर्भ को बाध्य करने के लिए पता ऑपरेटर का उपयोग नहीं करते हैं। –

1

इसके बजाय int* b के रूप में पढ़ने का, int *b के रूप में पढ़ "ख int करने के लिए एक सूचक है"। फिर, आपके पास & एंटी -* के रूप में है: * बी एक int है। *b का पता &*b है, या बस बी।

-2

मुझे लगता है कि उत्तर अच्छी तरह से हो सकता है "क्योंकि यह तरीका है & आर ने किया।"

डाउनवॉटिंग मूर्ख। समझाओ कि मैं गलत क्यों हूं।

के & आर वे हैं जिन्होंने निर्णय लिया कि पॉइंटर्स घोषित करने के लिए सी सिंटैक्स क्या था।

यह int & x नहीं है; int * x के बजाय; आर

3

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

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

मुझे याद है कि हमें संदर्भ देने के लिए एम्पर्सेंड के अर्थ को अधिभारित करने से सी ++ बहुत भ्रमित हो रहा है। किसी भी और पात्रों का उपयोग करने से बचने के अपने बेताब प्रयास में, जो सी का उपयोग कर अंतरराष्ट्रीय दर्शकों द्वारा उचित था और कुंजीपटल सीमाओं के साथ ज्ञात मुद्दों, उन्होंने भ्रम का एक प्रमुख स्रोत जोड़ा।

सी ++ में मदद करने वाली एक चीज पूर्व-तैयार डीरफ्रेंस किए गए पॉइंटर्स के संदर्भों के बारे में सोचने के लिए है। & का उपयोग करने के बजाय कुछ तर्कसंगत होने पर, जब आप कुछ वैरिएबल परिभाषित करते हैं तो आप पिछली बार एम्पर्सेंड का उपयोग कर चुके हैं। फिर फिर, यह आपको और भी भ्रमित कर सकता है!

मेरे पालतू में से एक से नफरत करता है, जो मैं एप्पल के ऑब्जेक्टिव-सी नमूनों में प्रख्यापित देखने के लिए दुखी था, लेआउट शैली int *someIntPointer बजाय int* someIntPointer

IMHO है, चर के साथ तारांकन रखने एक पुराने ढंग सी है अपने डेटा प्रकार पर चर को परिभाषित करने के तरीके के मैकेनिक्स पर जोर देने के दृष्टिकोण।

डेटा प्रकार someIntPointer सचमुच एक पूर्णांक के लिए एक सूचक है और घोषणा को प्रतिबिंबित करना चाहिए। इस आवश्यकता है कि आप प्रत्येक पंक्ति में एक चर घोषित करने के लिए नेतृत्व करता है, इस तरह के रूप सूक्ष्म कीड़े से बचने के लिए:

int* a, b; // b is a straight int, was that our intention? 

int *a, *b; // old-style C declaring two pointers 

int* a; 
int* b; // b is another pointer to an int 

जबकि लोगों का तर्क है कि क्षमता एक ही लाइन पर मिश्रित संकेत और मूल्यों की घोषणा करने, जानबूझकर, एक शक्तिशाली है सुविधा, मैंने देखा है कि यह सूक्ष्म बग और भ्रम की ओर ले जाता है।

+0

+1, घोषणा वाक्यविन्यास पर महान टिप्पणी। वास्तव में –

4

मुझे लगता है कि डेनिस रिची The Development of the C Language में यह उत्तर दिया:

इस तरह के एक बना प्रकार की प्रत्येक वस्तु के लिए, वहाँ पहले से ही था के लिए एक रास्ता अंतर्निहित वस्तु का उल्लेख: सूचकांक सरणी, कॉल फ़ंक्शन, पॉइंटर पर इंडिकेशन ऑपरेटर का उपयोग करें। एनालॉजिकल तर्क मिररिंग नामों के लिए घोषणा सिंटैक्स के लिए नामों के लिए घोषणापत्र वाक्यविन्यास का कारण बनता है जिसमें नाम आमतौर पर दिखाई देते हैं। इस प्रकार,

int i, *pi, **ppi; 

एक पूर्णांक, एक पूर्णांक के लिए सूचक, एक पूर्णांक के लिए सूचक को एक सूचक की घोषणा। इन घोषणाओं का सिंटैक्स अवलोकन को प्रतिबिंबित करता है कि अभिव्यक्ति में उपयोग किए जाने पर i, * pi, और ** ppi सभी int प्रकार उत्पन्न करते हैं। इसी तरह,

int f(), *f(), (*f)(); 

एक पूर्णांक, एक पूर्णांक, एक पूर्णांक लौटने एक कार्य करने के लिए एक सूचक के लिए एक सूचक वाला फ़ंक्शन फ़ंक्शन घोषित;

int *api[10], (*pai)[10]; 

पूर्णांकों की ओर इशारा की एक सरणी, और पूर्णांकों की एक सरणी के लिए एक सूचक की घोषणा। इन सभी मामलों में एक चर के घोषणापत्र जैसा अभिव्यक्ति में इसका उपयोग होता है जिसका प्रकार घोषणा के सिर पर नामित एक है।

तो हम सूचक को घोषित करने के लिए type * var का उपयोग करते हैं क्योंकि यह सूचक के उपयोग (dereferencing) को दर्पण करने की घोषणा की अनुमति देता है।

इस लेख में, रिची भी बताता है कि "एनबी", "बी" प्रोग्रामिंग भाषा की एक विस्तारित संस्करण में, वह int pointer[] के रूप में करने का विरोध किया int array[10] इस्तेमाल किया एक int के लिए सूचक घोषित करने के लिए, int रों की एक सरणी घोषित करने के लिए ।

+0

। और मैं int कर रहा हूँ, और मैं; यह अवैध होगा, क्योंकि मैं int उत्पन्न नहीं करता। यही कारण है कि यह सी में उपयोग नहीं कर रहा है और इस प्रकार सी ++ में। अफसोस की बात है, सी ++ ने इस समरूपता के साथ तोड़ दिया, और int &a = i; वैध कोड बनाया, यहां तक ​​कि "और मैं" int उत्पन्न नहीं करता है :( –

संबंधित मुद्दे