2013-08-29 4 views
7

क्या यह हमेशा मामला है, मेरा मतलब है कि सरणी नाम हमेशा सरणी के पहले तत्व के लिए एक सूचक होता है। ऐसा क्यों है? क्या यह कुछ कार्यान्वयन थोड़ी चीज या भाषा सुविधा है?सरणी का नाम सरणी के पहले तत्व के लिए सूचक क्यों है?

+3

http://c-faq.com/aryptr/index.html – NPE

+2

यह नहीं एक सूचक की एक पढ़ा है; इसका एक * पता *। मैंने अभी तक इस तथ्य को संवाद करने का सबसे आसान तरीका यह समझना है कि "पॉइंटर्स" * वेरिएबल्स * हैं * * पकड़ * पते; सरणी * * पते हैं। आप एक सूचक द्वारा आयोजित पते को संशोधित कर सकते हैं। कहा-वही * नहीं * कुछ है जो आप किसी सरणी में कर सकते हैं। – WhozCraig

+0

@ एनपीई लिंक बहुत उपयोगी है। धन्यवाद। – chanzerre

उत्तर

13

एक सरणी नाम स्वयं एक सूचक नहीं है, लेकिन अधिकांश संदर्भों में सरणी के पहले तत्व को पॉइंटर में क्षय करता है। ऐसा इसलिए है क्योंकि भाषा इसे इस तरह परिभाषित करती है। जब यह sizeof ऑपरेटर के संकार्य है सिवाय

, _Alignof ऑपरेटर, या एकल:

C11 6.3.2.1 Lvalues, सरणियों, और समारोह designators, पैरा 3 से

& ऑपरेटर, या एक सरणी प्रारंभ करने के लिए प्रयुक्त एक स्ट्रिंग शाब्दिक है, एक अभिव्यक्ति जिसमें "प्रकार टाइप करें" प्रकार के साथ एक अभिव्यक्ति में परिवर्तित किया गया है "पॉइंटर से टाइप "जो कि सरणी ऑब्जेक्ट के प्रारंभिक तत्व को इंगित करता है और एक अंतराल नहीं है।

आप comp.lang.c FAQ की Arrays and Pointers अनुभाग से इस विषय (और सूक्ष्म शामिल व्यवहार के बारे में बहुत सारे) के बारे में अधिक सीख सकते हैं।

संपादकीय एक तरफ: सी ++ में एक ही तरह का व्यवहार होता है, हालांकि भाषा इसे थोड़ा अलग तरीके से निर्दिष्ट करती है। संदर्भ के लिए, एक सी ++ 11 मसौदे से मैं यहाँ है, 4.2 सरणी-टू-सूचक रूपांतरण, अनुच्छेद 1:

एक lvalue या प्रकार के rvalue "NT की सरणी" या "अज्ञात की सरणी T की बाध्य "प्रकार के एक रैल्यू में परिवर्तित किया जा सकता है" सूचक T "। परिणाम सरणी के पहले तत्व के लिए एक सूचक है।

+2

आप N1570 ड्राफ़्ट उद्धृत कर रहे हैं। प्रकाशित सी 11 मानक '_Alignof' के संदर्भ को छोड़ देता है क्योंकि, किसी भी कारण से,' _Alignof' केवल एक संश्लेषित प्रकार के नाम पर लागू किया जा सकता है, अभिव्यक्ति के लिए नहीं। –

+0

अद्यतन के लिए धन्यवाद! –

+0

@ किथ थॉम्पसन एन1570 और प्रकाशित संस्करण के बीच अंतरों की कहीं भी एक सूची है? –

2

कार्ल Norum सवाल पर भाषा-वकील जवाब दिया (और उस पर मेरी वोट दें मिला), यहां कार्यान्वयन विस्तार जवाब आता है:

कंप्यूटर करने के लिए

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

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

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

यह लाभ यह है कि सरणी पहुंच excrutiatingly सरल हैं था, वे इंडेक्स को सरणी में ऑब्जेक्ट के आकार के साथ गुणा करने और पॉइंटर को ऑफसेट जोड़कर पॉइंटर अंकगणित के मामले में क्षय हो जाते हैं। यही कारण है कि a[5] बिल्कुल 5[a] जैसा ही है, यह *(a + 5) के लिए एक शॉर्टेंड है। केवल आरंभ पता गणना की जानी चाहिए:

एक और प्रदर्शन से संबंधित पहलू यह है कि यह एक सरणी से एक subarray बनाने के लिए excrutiatingly सरल है। ऐसा कुछ भी नहीं है जो हमें डेटा को एक नई सरणी में कॉपी करने के लिए मजबूर करेगा, हमें बस सही आकार का उपयोग करना याद रखना होगा ...

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

+1

इसके अलावा, पूरे सरणी ऑब्जेक्ट से निपटने के बजाए, अलग-अलग तत्वों को पॉइंटर्स द्वारा सरणी में हेरफेर करने से, इस तथ्य के कारण समस्याओं से बचा जाता है, उदाहरण के लिए, 'int [9] 'और' int [10]' अलग-अलग प्रकार हैं। और बहुत जल्दी सी (प्री-के एंड आर) में, एक सरणी ऑब्जेक्ट को घोषित करने से वास्तव में सरणी और पॉइंटर ऑब्जेक्ट दोनों बनाया गया था; जब संरचनाओं के सरणी सदस्यों को पेश किया गया था तब यह बदल दिया गया था, क्योंकि एक संरचना ऑब्जेक्ट को दूसरे पर कॉपी करते समय सूचक मूल्य को बनाए रखने का कोई अच्छा तरीका नहीं था। –

+0

@ किथ थॉम्पसन के एंड आर से पहले एक सी थी? – glglgl

+0

@glglgl: के एंड आर पहला संस्करण 1 9 78 में प्रकाशित हुआ था; सी के विकास के बारे में 1 9 6 9 शुरू हुआ, और बी और बीसीपीएल की पिछली भाषाओं पर आधारित था। http://cm.bell-labs.com/cm/cs/who/dmr/chist.html –

8

इस व्यवहार के लिए ऐतिहासिक कारण here पाया जा सकता है।

सी बी (जाने वाली आकृति) नाम की एक पूर्व भाषा से लिया गया था। बी एक टाइपहीन भाषा थी, और स्मृति को "कोशिकाओं" की रैखिक सरणी के रूप में माना जाता था, मूल रूप से हस्ताक्षरित पूर्णांक।

बी में, जब आप एक एन-तत्व वाली सरणी की घोषणा की,

auto a[10]; 

एन कोशिकाओं सरणी के लिए आबंटित किया गया के रूप में, और एक अन्य सेल पहला तत्व है, जो था की पता स्टोर करने के लिए अलग सेट किया गया था परिवर्तनीय a से बाध्य। सी में के रूप में, सरणी अनुक्रमण सूचक अंकगणित के माध्यम से किया गया था:

a[j] == *(a+j) 

यह बहुत अच्छी तरह से काम किया जब तक रिची उदाहरण वह समाचार पत्र में देता है सी struct प्रकार जोड़ने शुरू कर दिया है एक काल्पनिक फाइल सिस्टम प्रविष्टि है, जो एक नोड है आईडी के बाद नाम:

struct { 
    int inumber; 
    char name[14]; 
}; 

वह डिस्क पर डेटा से मेल खाने के लिए संरचना प्रकार की सामग्री चाहता था; एक पूर्णांक के लिए 2 बाइट तुरंत नाम के लिए 14 बाइट्स के बाद। सूचक के सरणी के पहले तत्व में पॉइंटर को छूने के लिए कोई अच्छी जगह नहीं थी।

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

यह संयोगवश, यही वजह है कि एक सरणी अभिव्यक्ति एक काम का लक्ष्य नहीं हो सकता है; यह प्रभावी रूप से 3 = 4; लिखने जैसा ही है - आप किसी अन्य मान को मान असाइन करने का प्रयास करेंगे।

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