शून्य पॉइंटर के लिए पता शून्य का उपयोग क्यों किया जाता है?


121

सी (या उस बात के लिए सी ++) में, पॉइंटर्स विशेष हैं यदि उनके पास मूल्य शून्य है: मुझे उनकी स्मृति को मुक्त करने के बाद पॉइंटर्स को शून्य पर सेट करने की सलाह दी जाती है, क्योंकि इसका मतलब है कि सूचक को फिर से मुक्त करना खतरनाक नहीं है; जब मैं मॉलॉक कहता हूं तो यह मूल्य शून्य के साथ एक पॉइंटर लौटाता है यदि यह मुझे मेमोरी नहीं दे सकता है; मैं if (p != 0)सभी समय का उपयोग यह सुनिश्चित करने के लिए करता हूं कि पास किए गए पॉइंटर्स वैध हैं, आदि।

लेकिन जब से मेमोरी एड्रेसिंग 0 से शुरू होती है, क्या 0 किसी अन्य के समान वैध एड्रेस नहीं है? यदि यह है तो अशक्त बिंदुओं को संभालने के लिए 0 का उपयोग कैसे किया जा सकता है? इसके बजाय एक नकारात्मक संख्या शून्य क्यों नहीं है?


संपादित करें:

अच्छे उत्तरों का एक गुच्छा। मैं संक्षेप में बताऊंगा कि मेरे अपने मन के रूप में व्यक्त किए गए उत्तरों में यह कहा गया है और मुझे आशा है कि यदि मैं गलत समझ लेता हूं तो समुदाय मुझे सुधार देगा।

  • प्रोग्रामिंग में सब कुछ की तरह यह एक अमूर्त है। बस एक निरंतरता, वास्तव में पते से संबंधित नहीं है। 0. C ++ 0x कीवर्ड को जोड़कर इस पर जोर देता है nullptr

  • यह एक पते का अमूर्त भी नहीं है, यह सी मानक द्वारा निर्दिष्ट निरंतर है और संकलक इसे किसी अन्य संख्या में अनुवाद कर सकता है जब तक यह सुनिश्चित करता है कि यह "वास्तविक" पते के बराबर नहीं है, और अन्य अशक्त बिंदुओं के बराबर है यदि 0 नहीं है मंच के लिए उपयोग करने के लिए सबसे अच्छा मूल्य।

  • मामले में, यह एक अमूर्त नहीं है, जो शुरुआती दिनों में मामला था, पता 0 का उपयोग सिस्टम द्वारा किया जाता है और प्रोग्रामर को सीमा से दूर किया जाता है।

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

  • यदि किसी संख्या को हमेशा एक डायटाइप द्वारा दर्शाया जाता है, तो यह 0. है (शायद 1 भी है। मुझे लगता है कि एक-बिट पूर्णांक जो 0 या 1 होगा यदि अहस्ताक्षरित है, या केवल हस्ताक्षर किए गए बिट पर हस्ताक्षर किए हैं, या दो बिट पूर्णांक हैं जो हो सकता है [-2, 1]। लेकिन तब आप बस 0 शून्य और 1 मेमोरी में एकमात्र सुलभ बाइट होने के लिए जा सकते थे।)

फिर भी कुछ है जो मेरे दिमाग में अनसुलझा है। स्टैक ओवरफ्लो प्रश्न एक विशिष्ट निश्चित पते की ओर इशारा करता है, मुझे बताता है कि भले ही अशक्त सूचक के लिए 0 एक अमूर्त है, अन्य सूचक मान आवश्यक नहीं हैं। यह मुझे एक और स्टैक ओवरफ्लो प्रश्न पोस्ट करने की ओर ले जाता है, क्या मैं कभी भी पता शून्य तक पहुंचना चाहता हूं?


11
आप आसानी से बदल सकते हैं if (p != 0), if (p)जो कि C और C ++ में एक सामान्य मुहावरा है, हालाँकि अगर आप जावा को अपनाते हैं तो आपको इस आदत से बाहर निकलना होगा।
पॉल टॉम्बलिन

14
दो बार कुछ हटाने का मतलब है कि आपका कोड गलत है। मैं संकेत देने के खिलाफ सलाह देता हूं कि आप अशक्त हो सकते हैं ताकि आप समस्या को ठीक कर सकें और उसे दबा सकें। किसी भी स्थिति में, आप यह मान लेते हैं कि कोई पता कुछ पूर्णांक है। यह आवश्यक रूप से सच नहीं है, और 0 केवल कुछ वास्तविक सूचक मान का प्रतिनिधित्व करता है जो कार्यान्वयन-विशिष्ट है। एक "नकारात्मक पता" समझदारी से नहीं बनता है।
GManNickG

6
@ मन: शायद एक अच्छे विचार के लिए सूचक को एक पते पर सेट करना जो दुर्घटना को मजबूर करेगा, जैसे कि 0xDEADBEEF
बिली ओनली

5
सवाल जो कभी नहीं मरेगा!

8
@ नोहा: बिंदु को अशक्त करने के लिए सेट किया गया है -> प्रोग्रामिंग त्रुटियों को छिपाएं, अशक्त करने के लिए सेट न करें -> प्रोग्रामिंग त्रुटियों को ढूंढें। मैं आपके बारे में नहीं जानता, लेकिन मैं अपना कोड सही रखना चाहूंगा।
GManNickG

जवाबों:


65

2 अंक:

  • स्रोत कोड में केवल निरंतर मान 0 शून्य सूचक है - संकलक कार्यान्वयन रनिंग कोड में जो भी मूल्य चाहता है या उसकी आवश्यकता है का उपयोग कर सकता है। कुछ प्लेटफ़ॉर्म का एक विशेष पॉइंटर मान है जो 'अमान्य' है जिसे कार्यान्वयन नल पॉइंटर के रूप में उपयोग कर सकता है। सी एफएक्यू में एक प्रश्न है, "गंभीरता से, क्या किसी भी वास्तविक मशीनों ने वास्तव में नॉनज़रो नल पॉइंटर्स का उपयोग किया है, या विभिन्न प्रकारों के लिए पॉइंटर्स के लिए अलग-अलग प्रतिनिधित्व है?" , जो कई प्लेटफार्मों को इंगित करता है जिन्होंने 0 की इस संपत्ति का उपयोग सी स्रोत में शून्य पॉइंटर होने के दौरान रनटाइम के दौरान अलग-अलग तरीके से किया। C ++ मानक में एक नोट है जो स्पष्ट करता है कि "मूल्य शून्य के साथ एक अभिन्न निरंतर अभिव्यक्ति को परिवर्तित करना हमेशा एक शून्य सूचक देता है,"

  • एक नकारात्मक मान एक पते के रूप में मंच द्वारा उपयोग करने योग्य हो सकता है - सी मानक को केवल एक शून्य सूचक को इंगित करने के लिए उपयोग करने के लिए कुछ चुनना था, और शून्य चुना गया था। अगर अन्य प्रहरी मूल्यों पर विचार किया जाता है तो मैं ईमानदारी से निश्चित नहीं हूं।

एक शून्य सूचक के लिए केवल आवश्यकताएं हैं:

  • यह एक वास्तविक वस्तु के लिए एक सूचक को असमान की तुलना करने की गारंटी है
  • किसी भी दो अशक्त संकेत बराबर की तुलना करेंगे (C ++ इसे इस तरह से परिष्कृत करता है कि यह केवल उसी प्रकार के संकेत के लिए पकड़ की आवश्यकता है)

12
+1 मुझे संदेह है कि केवल ऐतिहासिक कारणों से 0 चुना गया था। (0 एक शुरुआती और अमान्य पता, अधिकांश समय।) बेशक ऐसी धारणा हमेशा सही नहीं होती, लेकिन 0 बहुत अच्छी तरह से काम करती है।
GManNickG

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

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

10
मिनिक्स 16 बिट कंपाइलर ने NULL के लिए 0xFFFF का उपयोग किया।
यहोशू

3
कई एम्बेडेड सिस्टम में, 0 एक मान्य पता है। मान -1 (सभी बिट्स एक) भी एक वैध पता है। डेटा 0. पते पर शुरू होने पर रोम के लिए चेकसम की गणना करना मुश्किल है:
थॉमस मैथ्यू

31

ऐतिहासिक रूप से, 0 से शुरू होने वाला पता स्थान हमेशा ROM था, जिसका उपयोग कुछ ऑपरेटिंग सिस्टम या निम्न स्तर की बाधा से निपटने के लिए किया जाता था, आजकल, चूंकि सब कुछ आभासी है (पता स्थान सहित), ऑपरेटिंग सिस्टम किसी भी पते पर किसी भी आवंटन को मैप कर सकता है, इसलिए यह कर सकता है विशेष रूप से पता 0 पर कुछ भी आवंटित न करें।


6
यह बहुत ज्यादा है। यह ऐतिहासिक सम्मेलन के द्वारा होता है, और पहले जोड़ को हैंडलर के लिए उपयोग किया जाता था, इस प्रकार यह सामान्य कार्यक्रमों के लिए अनुपयोगी होता है। इसके अलावा, 0 "खाली" है, जिसका कोई मूल्य नहीं / सूचक के रूप में व्याख्या की जा सकती है।
टॉमटॉम

15

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


5
@ जस्टिन: आपने गलत समझा। स्थिर 0 हमेशा अशक्त सूचक होता है। @ मीडोर क्या कह रहा है कि यह संभव है कि अशक्त सूचक (स्थिर 0 द्वारा इंगित) पता शून्य के अनुरूप नहीं है। कुछ प्लेटफ़ॉर्म पर, एक शून्य पॉइंटर ( int* p = 0) बनाने से एक ऐसा पॉइंटर बन सकता है जिसमें 0xdeadbeefकोई मान या कोई अन्य मान हो जो इसे पसंद करता है। 0 एक शून्य सूचक है, लेकिन शून्य को संबोधित करने के लिए एक शून्य सूचक जरूरी सूचक नहीं है। :)
जलफ

NULL पॉइंटर एक आरक्षित मूल्य है और संकलक के आधार पर कोई भी बिट पैटर्न हो सकता है। NULL पॉइंटर का मतलब यह नहीं है कि यह 0. को संबोधित करता है
शारजील अज़ीज़

3
लेकिन @Jalf, निरंतर 0 नहीं है हमेशा नल पॉइंटर। यह वह है जो हम लिखते हैं जब हम चाहते हैं कि कंपाइलर हमारे लिए प्लेटफॉर्म के वास्तविक नल पॉइंटर को भरें । व्यवहार में, नल पॉइंटर आमतौर पर करता अनुरूप पता शून्य करने के लिए, हालांकि, और मैं पूछ क्यों है के रूप में जोएल के प्रश्न की व्याख्या। माना जाता है कि उस पते पर स्मृति का एक वैध बाइट है, आखिर क्यों एक गैर-मौजूद बाइट के गैर-मौजूद पते का उपयोग न करके एक वैध बाइट को खेलने से हटा दिया जाए? (मैं लिख रहा हूं जोएल की कल्पना मैं सोच रहा था, एक सवाल नहीं जो मैं खुद से पूछ रहा हूं।)
रोब केनेडी

@ रब: सॉर्ट। मुझे पता है कि आपका क्या मतलब है, और आप सही हैं, लेकिन मैं I. :) निरंतर पूर्णांक 0 एक स्रोत कोड स्तर पर अशक्त सूचक का प्रतिनिधित्व करता है। एक शून्य सूचक की तुलना में 0 पैदावार सच है। एक पॉइंटर को 0 असाइन करना जो पॉइंटर को अशक्त करने के लिए सेट करता है। 0 है नल पॉइंटर। लेकिन एक शून्य पॉइंटर का वास्तविक इन-मेमोरी प्रतिनिधित्व शून्य बिट पैटर्न से अलग हो सकता है। (वैसे भी, मेरी टिप्पणी @ जस्टिन की अब हटाई गई टिप्पणी के जवाब में थी, न कि @ जोएल के सवाल पर। :)
jalf

@jalf @Rob आपको स्पष्ट करने के लिए कुछ शर्तों की आवश्यकता है, मुझे लगता है। :) ull4.10 / 1 से: "एक शून्य सूचक स्थिरांक पूर्णांक प्रकार का एक अभिन्न स्थिर अभिव्यक्ति है जो शून्य का मूल्यांकन करता है। एक अशक्त सूचक स्थिरांक को एक सूचक प्रकार में परिवर्तित किया जा सकता है; परिणाम उस प्रकार का अशक्त पॉटर मान है और ऑब्जेक्ट या पॉइंटर से फ़ंक्शन प्रकार के लिए पॉइंटर के हर दूसरे मूल्य से अलग है। "
GManNickG

15

आपको पॉइंटर संदर्भ में निरंतर शून्य का अर्थ गलत समझना चाहिए।

न तो C में और न ही C ++ पॉइंटर्स में "शून्य मान हो सकता है"। संकेत अंकगणितीय वस्तु नहीं हैं। वे "शून्य" या "नकारात्मक" या उस प्रकृति के कुछ भी जैसे संख्यात्मक मान नहीं सकते। तो "पॉइंटर्स ... वैल्यू जीरो" के बारे में आपके कथन का कोई मतलब नहीं है।

C & C ++ पॉइंटर्स में आरक्षित नल-सूचक मान हो सकता है । नल-पॉइंटर मूल्य के वास्तविक प्रतिनिधित्व का किसी "शून्य" से कोई लेना-देना नहीं है। किसी दिए गए प्लेटफ़ॉर्म के लिए यह बिल्कुल उपयुक्त हो सकता है। यह सच है कि अधिकांश फलक पर अशक्त-सूचक मान भौतिक रूप से वास्तविक शून्य पता मान द्वारा दर्शाया जाता है। हालाँकि, यदि कुछ प्लेटफ़ॉर्म एड्रेस 0 पर वास्तव में किसी उद्देश्य के लिए उपयोग किया जाता है (यानी आपको एड्रेस 0 पर ऑब्जेक्ट बनाने की आवश्यकता हो सकती है), तो ऐसे प्लेटफ़ॉर्म पर नल-पॉइंटर वैल्यू की संभावना सबसे अलग होगी। यह भौतिक रूप से 0xFFFFFFFFपता मूल्य या पते के मूल्य के रूप में दर्शाया जा सकता है 0xBAADBAAD, उदाहरण के लिए।

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

संक्षेप में, यह तथ्य कि आप 0अशक्त-पॉइंटर मान उत्पन्न करने के लिए अपने sorce कोड का उपयोग करते हैं , इसका मतलब यह नहीं है कि null-पॉइंटर मान किसी तरह से संबोधित करने के लिए बंधा हुआ है 00आपके द्वारा अपने स्रोत कोड में उपयोग सिर्फ "वाक्यात्मक चीनी" बिल्कुल वास्तविक भौतिक पता अशक्त-सूचक मान "ओर इशारा करते हुए" है से कोई संबंध नहीं है।


3
<उद्धरण> पॉइंटर्स अंकगणित ऑब्जेक्ट नहीं हैं </ उद्धरण> पॉइंटर अंकगणित सी और सी ++ में काफी अच्छी तरह से परिभाषित है। आवश्यकता का हिस्सा यह है कि दोनों संकेत एक ही समग्र के भीतर इंगित करते हैं। अशक्त सूचक किसी भी समग्र को इंगित नहीं करता है इसलिए सूचक अंकगणितीय अभिव्यक्तियों में इसका उपयोग करना अवैध है। उदाहरण के लिए, यह गारंटी नहीं है कि (p1 - nullptr) - (p2 - nullptr) == (p1 - p2)
बेन वोइगट

5
@ बान वायगट: भाषा विनिर्देश अंकगणितीय प्रकार की धारणा को परिभाषित करता है । मैं केवल इतना कह रहा हूं कि सूचक प्रकार अंकगणितीय प्रकारों की श्रेणी से संबंधित नहीं हैं। सूचक अंकगणित एक अलग और पूरी तरह से असंबंधित कहानी है, एक मात्र भाषाई संयोग है।
बजकर

1
कोई व्यक्ति अंकगणितीय वस्तुओं को कैसे पढ़ रहा है, यह जानना चाहिए कि इसका अर्थ है "अंकगणित प्रकार के अर्थ में" और "अंकगणितीय ऑपरेटरों के अर्थ में" (जिनमें से कई संकेत पर उपयोगी हैं) या "सूचक अंकगणित के अर्थ में"। जहां तक भाषाई संयोग का संबंध है, अंकगणित वस्तु के साथ आम में अधिक अक्षर हैं सूचक अंकगणित से अंकगणित प्रकार । इसी समय, मानक पॉइंटर मूल्य के बारे में बात करता है । मूल पोस्टर का मतलब संभवतः सूचक मान के बजाय एक सूचक का पूर्णांक प्रतिनिधित्व था , और स्पष्ट रूप से 0.NULL
Vott

खैर, उदाहरण के लिए शब्द स्केलर ऑब्जेक्ट्स C / C ++ शब्दावली में केवल स्केलर प्रकार की वस्तुओं ( POD ऑब्जेक्ट्स = POD प्रकारों की वस्तुओं ) के लिए एक शॉर्टहैंड है । मैंने अंकगणित वस्तुओं का उपयोग ठीक उसी तरह से किया है, जिसका अर्थ है अंकगणित के प्रकार । मैं उम्मीद करता हूं कि "कोई" इसे इस तरह से समझेगा। कोई है जो हमेशा एक स्पष्टीकरण के लिए नहीं पूछ सकता है।
ए.टी.

1
मैंने एक ऐसी प्रणाली पर काम किया जहां (जहाँ तक हार्डवेयर का संबंध था) शून्य 0xffffffff था और 0 पूरी तरह से वैध पता था
pm100

8

लेकिन जब से मेमोरी एड्रेसिंग 0 से शुरू होती है, क्या 0 किसी अन्य के समान वैध एड्रेस नहीं है?

कुछ / कई / सभी ऑपरेटिंग सिस्टम पर, मेमोरी एड्रेस 0 किसी तरह से विशेष है। उदाहरण के लिए, इसे अक्सर अमान्य / गैर-मौजूद स्मृति में मैप किया जाता है, जो इसे एक्सेस करने का प्रयास करने पर अपवाद का कारण बनता है।

इसके बजाय एक नकारात्मक संख्या शून्य क्यों नहीं है?

मुझे लगता है कि सूचक मानों को आमतौर पर अहस्ताक्षरित संख्याओं के रूप में माना जाता है: अन्यथा उदाहरण के लिए एक 32-बिट सूचक केवल 4 जीबी के बजाय 2 जीबी मेमोरी को संबोधित करने में सक्षम होगा।


4
मैंने एक उपकरण पर कोडित किया है जहां पता शून्य एक वैध पता था, और कोई मेमोरी सुरक्षा नहीं थी। अशक्त बिंदु भी ऑल-बिट्स-शून्य थे; यदि आपने गलती से एक नल सूचक को लिखा है, तो आपने ओएस सेटिंग्स पर विस्फोट किया जो शून्य पते पर थे; उल्लसितता आमतौर पर सुनिश्चित नहीं की गई।
MM

1
हां: एक गैर-संरक्षित-मोड x86 सीपीयू पर, उदाहरण के लिए, पता 0 इंटरप्ट वेक्टर टेबल है
क्रिस डब्ल्यूडी

@ क्रिस: गैर-संरक्षित-मोड x86 पर, विशेष रूप से पता शून्य, डिवाइड-बाय-जीरो इंटरप्ट वेक्टर है, जो कुछ कार्यक्रमों में लेखन के लिए पूरी तरह से वैध कारण हो सकता है।
सुपरकैट

यहां तक ​​कि उन प्लेटफार्मों पर भी जहां उपयोग करने योग्य भंडारण भौतिक पते पर शुरू होता है, शून्य, एक सी कार्यान्वयन आसानी से किसी वस्तु को धारण करने के लिए पते के शून्य का उपयोग कर सकता है जिसका पता कभी नहीं लिया जाता है, या फिर बस अप्रयुक्त स्मृति के पहले शब्द को छोड़ दें। अधिकांश प्लेटफ़ॉर्म पर, तुलना-के साथ शून्य तुलना-के-साथ-कुछ और के रूप में एक निर्देश बचाता है, इसलिए यहां तक ​​कि भंडारण के पहले शब्द को बर्बाद करना शून्य के लिए गैर-शून्य पते का उपयोग करने से सस्ता होगा। ध्यान दें कि कोई आवश्यकता नहीं है कि सी स्टैंडर्ड द्वारा कवर की गई चीजों के पते (जैसे I / O पोर्ट या इंटरप्ट वैक्टर) असमान की तुलना अशक्त से करते हैं, न ही ...
सुपरकैट

... सिस्टम प्रक्रिया नल-पॉइंटर किसी भी अन्य से अलग तरीके से एक्सेस करती है, इसलिए ऑल-बिट्स-जीरो आमतौर पर उन सिस्टमों पर भी "अशक्त" के लिए एक अच्छा पता है, जहां भौतिक स्थान शून्य तक पहुंच उपयोगी और सार्थक होगी।
सुपरकैट

5

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

(अधिकांश ISAs केवल ALU निर्देशों पर झंडे सेट करते हैं, हालांकि लोड नहीं करते हैं। और आमतौर पर आप सी स्रोत को पार्स करते समय कंपाइलर को छोड़कर कंप्यूटेशन के माध्यम से उत्पादन नहीं कर रहे हैं । लेकिन कम से कम आपको एक मनमाना पॉइंटर-चौड़ाई स्थिर करने की आवश्यकता नहीं है। के खिलाफ तुलना करें।)

कमोडोर पेट, विक 20 और सी 64 पर जो पहली मशीनें थीं जिन पर मैंने काम किया था, रैम की शुरुआत लोकेशन 0 से हुई थी, इसलिए यदि आप वास्तव में चाहते थे तो अशक्त सूचक का उपयोग करके पढ़ना और लिखना पूरी तरह से मान्य था।


3

मुझे लगता है कि यह सिर्फ एक सम्मेलन है। अमान्य सूचक को चिह्नित करने के लिए कुछ मूल्य होना चाहिए।

आप केवल पते की जगह का एक बाइट खो देते हैं, जो शायद ही कभी एक समस्या हो।

कोई नकारात्मक संकेत नहीं हैं। पॉइंटर्स हमेशा अहस्ताक्षरित होते हैं। इसके अलावा अगर वे नकारात्मक हो सकते हैं तो आपके सम्मेलन का मतलब यह होगा कि आप आधे पते की जगह खो देंगे।


नोट: आप वास्तव में पता स्थान नहीं खोते हैं; आप ऐसा करने के लिए 0 को संबोधित करने के लिए एक पॉइंटर प्राप्त कर सकते हैं char *p = (char *)1; --p;:। चूंकि एक अशक्त सूचक पर व्यवहार मानक द्वारा अपरिभाषित है, इसलिए यह प्रणाली pवास्तव में पता 0 पढ़ और लिख सकती है , पता देने के लिए वेतन वृद्धि 1, आदि
MM

@MattMcNabb: एक कार्यान्वयन जहां पता शून्य एक मान्य हार्डवेयर पता है, वह पूरी तरह से वैध तरीके से पता शून्य के व्यवहार को परिभाषित कर सकता char x = ((char*)0);है और उस मान को x में संग्रहीत कर सकता है। इस तरह का कोड किसी भी कार्यान्वयन पर अपरिभाषित व्यवहार का उत्पादन करेगा, जो इसके व्यवहार को परिभाषित नहीं करता है, लेकिन यह तथ्य कि एक मानक कुछ कहता है, यह है कि यह क्या करेगा के लिए अपने स्वयं के विनिर्देशों की पेशकश करने से किसी भी तरह से मना नहीं करता है।
सुपरकैट

ITYM @supercat *(char *)0। यह सच है, लेकिन मेरे सुझाव में कार्यान्वयन *(char *)0को किसी अन्य अशक्त सूचक संचालन के व्यवहार को परिभाषित करने की आवश्यकता नहीं है ।
MM

1
@MattMcNabb: के व्यवहार char *p = (char*)1; --p;को केवल मानक द्वारा परिभाषित किया जाएगा यदि उस अनुक्रम को किसी वस्तु के पहले बाइट के अलावा किसी अन्य के लिए सूचक के बाद प्रदर्शन किया गया हो intptr_t, और उस कास्ट का परिणाम मान उत्पन्न करने के लिए हुआ हो 1 , और उस विशेष मामले में --pबाइट से पहले एक पॉइंटर का परिणाम निकलेगा, जिसका पॉइंटर वैल्यू, जब कास्ट किया जाता है intptr_t, तब प्राप्त होता है 1
सुपरकाट

3

यद्यपि C शून्य सूचक का प्रतिनिधित्व करने के लिए 0 का उपयोग करता है, लेकिन ध्यान रखें कि सूचक का मान स्वयं एक शून्य नहीं हो सकता है। हालांकि, अधिकांश प्रोग्रामर केवल उन सिस्टम का उपयोग करेंगे जहां नल पॉइंटर है, वास्तव में, 0।

लेकिन शून्य क्यों? खैर, यह एक पता है कि हर सिस्टम साझा करता है। और अक्सर कम पते ऑपरेटिंग सिस्टम के उद्देश्यों के लिए आरक्षित होते हैं, इस प्रकार मूल्य आवेदन कार्यक्रमों के लिए ऑफ-लिमिट होने के रूप में अच्छी तरह से काम करता है। सूचक को पूर्णांक मान का आकस्मिक असाइनमेंट शून्य और कुछ के रूप में समाप्त होने की संभावना है।


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

2

ऐतिहासिक रूप से एक एप्लिकेशन की कम मेमोरी सिस्टम संसाधनों द्वारा कब्जा कर ली गई थी। यह उन दिनों में था कि शून्य डिफ़ॉल्ट शून्य मान बन गया था।

हालांकि यह आधुनिक प्रणालियों के लिए आवश्यक रूप से सही नहीं है, फिर भी सूचक मूल्यों को किसी भी चीज़ पर सेट करना एक बुरा विचार है लेकिन स्मृति आवंटन ने आपको क्या सौंपा है।


2

इसे हटाने के बाद शून्य करने के लिए पॉइंटर सेट न करने के तर्क के बारे में ताकि भविष्य में "त्रुटियों का पर्दाफाश" हो सके ...

यदि आप वास्तव में चिंतित हैं, तो इस बारे में चिंतित हैं कि एक बेहतर दृष्टिकोण, जो काम करने की गारंटी है, वह जोर () का लाभ उठाने के लिए है:


...
assert(ptr && "You're deleting this pointer twice, look for a bug?");
delete ptr;
ptr = 0;
...

इसके लिए कुछ अतिरिक्त टाइपिंग की आवश्यकता होती है, और डिबग बिल्ड के दौरान एक अतिरिक्त चेक की आवश्यकता होती है, लेकिन आपको यह देना निश्चित है कि आप क्या चाहते हैं: नोटिस जब ptr 'दो बार' हटा दिया जाता है। टिप्पणी चर्चा में दिए गए विकल्प, सूचक को अशक्त करने के लिए सेट नहीं है ताकि आपको दुर्घटना हो जाए, बस सफल होने की गारंटी नहीं है। इससे भी बदतर, उपरोक्त के विपरीत, यह एक उपयोगकर्ता पर दुर्घटना (या बहुत बुरा!) पैदा कर सकता है अगर इनमें से एक "बग" शेल्फ के माध्यम से हो जाता है। अंत में, यह संस्करण आपको वास्तव में क्या होता है, यह देखने के लिए प्रोग्राम को चलाना जारी रखने देता है।

मुझे लगता है कि यह पूछे गए सवाल का जवाब नहीं देता है, लेकिन मुझे चिंता थी कि टिप्पणियों को पढ़ने वाला कोई व्यक्ति इस निष्कर्ष पर पहुंच सकता है कि यह 'अच्छा अभ्यास' माना जाता है कि संकेत 0 को सेट न करें यदि यह संभव है कि उन्हें मुफ्त में भेजा जाए () या दो बार हटाएं। उन कुछ मामलों में जब यह संभव है कि डिबगिंग टूल के रूप में अनिर्धारित व्यवहार का उपयोग करने के लिए यह एक अच्छा अभ्यास नहीं है। किसी को भी कभी भी एक बग का शिकार नहीं करना पड़ता है जो अंततः एक अवैध सूचक को हटाने के कारण होता है। इस प्रकार की त्रुटियां शिकार करने में घंटों का समय लेती हैं और लगभग पूरी तरह से अनपेक्षित तरीके से कार्यक्रम को प्रभावित करती हैं जो मूल समस्या को वापस ट्रैक करना असंभव है।


2

एक महत्वपूर्ण कारण क्यों कई ऑपरेटिंग सिस्टम नल पॉइंटर प्रतिनिधित्व के लिए ऑल-बिट्स-जीरो का उपयोग करते हैं, यह है कि इसका मतलब है memset(struct_with_pointers, 0, sizeof struct_with_pointers)और इसी तरह सभी बिंदुओं struct_with_pointersको शून्य बिंदुओं के अंदर सेट करेंगे । यह सी मानक द्वारा गारंटी नहीं है, लेकिन कई, कई कार्यक्रम इसे मानते हैं।


1

पुरानी DEC मशीनों में से एक (PDP-8, मुझे लगता है) में, C रनटाइम मेमोरी मेमोरी के पहले पेज की रक्षा करेगा ताकि उस ब्लॉक में मेमोरी तक पहुंचने के किसी भी प्रयास से एक अपवाद पैदा हो।


PDP-8 में कोई C संकलक नहीं था। PDP-11 में कोई मेमोरी सुरक्षा नहीं थी और VAX चुपचाप 0 से NULL पॉइंटर डेरेफेरेंस के लिए बदनाम था। मुझे यकीन नहीं है कि यह किस मशीन को संदर्भित करता है।
फुज

1

प्रहरी मूल्य की पसंद मनमाना है, और यह वास्तव में C ++ के अगले संस्करण (अनौपचारिक रूप से "C ++ 0x" के रूप में जाना जाता है, जिसे भविष्य में ISO C ++ 2011 के रूप में जाना जाता है) के परिचय के साथ संबोधित किया जा रहा है। कीवर्डnullptr एक शून्य मूल्यवान सूचक का प्रतिनिधित्व करने के लिए । C ++ में, 0 का मान किसी भी POD के लिए और डिफ़ॉल्ट कंस्ट्रक्टर के साथ किसी भी ऑब्जेक्ट के लिए इनिशियललाइज़ेशन एक्सप्रेशन के रूप में इस्तेमाल किया जा सकता है, और इसमें पॉइंटर इनिशियलाइज़ेशन के मामले में सेंटिनल वैल्यू असाइन करने का विशेष अर्थ है। एक नकारात्मक मान क्यों नहीं चुना गया, इसके लिए पते आमतौर पर 0 से 2 एन तक होते हैं-1 कुछ मानों के लिए। दूसरे शब्दों में, पते को आमतौर पर अहस्ताक्षरित मान के रूप में माना जाता है। यदि अधिकतम मूल्य को प्रहरी मूल्य के रूप में उपयोग किया जाता है, तो यह मेमोरी के आकार के आधार पर सिस्टम से सिस्टम में भिन्न होता है जबकि 0 हमेशा एक प्रतिनिधित्व करने योग्य पता होता है। इसका उपयोग ऐतिहासिक कारणों के लिए भी किया जाता है, क्योंकि मेमोरी एड्रेस 0 आमतौर पर कार्यक्रमों में अनुपयोगी होता है, और आजकल अधिकांश ओएस में मेमोरी के निचले पृष्ठ (भागों) में कर्नेल के कुछ हिस्से होते हैं, और इस तरह के पेज आमतौर पर इस तरह से संरक्षित होते हैं कि यदि एक प्रोग्राम (कर्नेल को बचाने) द्वारा छुआ हुआ (डिफरेंस्ड) एक गलती का कारण होगा।


1

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


0

शायद ही कोई ओएस आपको पता लिखने के लिए लिखने की अनुमति देता है 0. कम स्मृति में ओएस-विशिष्ट सामान को छड़ी करने के लिए यह सामान्य है; अर्थात्, आईडीटी, पेज टेबल, आदि (तालिकाओं को रैम में होना चाहिए, और उन्हें नीचे की तरफ चिपकाना आसान है और यह निर्धारित करने की तुलना में कि रैम का शीर्ष कहां है।) और इसके दाहिने दिमाग में कोई ओएस आपको नहीं देगा। सिस्टम टेबल को संपादित करें willy-nilly।

हो सकता है कि जब वे C को बनाते हैं, तो K & R के दिमाग में न हों, लेकिन यह (इस तथ्य के साथ कि 0 == null याद रखना बहुत आसान है) 0 को एक लोकप्रिय विकल्प बनाता है।


यह संरक्षित मोड में सच नहीं है, और वास्तव में, कुछ लिनक्स कॉन्फ़िगरेशन पर, आप वर्चुअल पते पर लिख सकते हैं 0.
L̲̳̳o̲̳̳n̲̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳

0

मूल्य 0एक विशेष मूल्य है जो विशिष्ट अभिव्यक्तियों में विभिन्न अर्थों को लेता है। संकेत के मामले में, जैसा कि कई बार बताया गया है, इसका उपयोग संभवतः इसलिए किया जाता है क्योंकि उस समय यह कहने का सबसे सुविधाजनक तरीका था "यहां डिफ़ॉल्ट प्रहरी मूल्य डालें"। एक स्थिर अभिव्यक्ति के रूप में, इसका कोई मतलब नहीं है बिटवेय शून्य (यानी, सभी बिट्स शून्य बिंदु पर) एक सूचक अभिव्यक्ति के संदर्भ में। C ++ में, कई प्रकार हैं जिनके पास बिटवाइरो शून्य प्रतिनिधित्व नहीं है NULLजैसे कि पॉइंटर सदस्य और पॉइंटर से सदस्य फ़ंक्शन।

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


0

इस धागे में पहले से ही बहुत अच्छे उत्तर हैं; 0अशक्त बिंदुओं के लिए मान को प्राथमिकता देने के कई अलग-अलग कारण हैं , लेकिन मैं दो और जोड़ने जा रहा हूं:

  • सी ++ में, शून्य-सूचक को इंगित करने से यह शून्य हो जाएगा।
  • कई प्रोसेसरों पर किसी मान को 0 पर सेट करने के लिए या किसी अन्य स्थिरांक के मुकाबले 0 के बराबर / नहीं के बराबर परीक्षण करना अधिक कुशल है।

0

यह C / C ++ में संकेत के कार्यान्वयन पर निर्भर है। कोई विशेष कारण नहीं है कि NULL एक पॉइंटर के असाइनमेंट में बराबर है।


-1

इसके ऐतिहासिक कारण हैं, लेकिन इसके अनुकूलन विकल्प भी हैं।

ओएस के लिए यह एक आम बात है कि यह स्मृति पृष्ठों के साथ 0. प्रदान करता है। यदि कोई प्रोग्राम उस मेमोरी पेज के हिस्से को एक पॉइंटर के रूप में व्याख्या करना चाहता है तो यह 0 है, इसलिए प्रोग्राम के लिए यह निर्धारित करना आसान है कि वह पॉइंटर है आरंभिक नहीं है। (यह तब अच्छी तरह से काम नहीं करता है जब एकरारहित फ़्लैश पृष्ठों पर लागू होता है)

एक और कारण यह है कि कई प्रोसेसर पर एक मान के समकक्ष का परीक्षण करना बहुत आसान है 0. यह कभी-कभी किसी भी अतिरिक्त निर्देशों के बिना एक मुफ्त तुलना की जाती है, और आमतौर पर किसी अन्य रजिस्टर में शून्य मान प्रदान करने की आवश्यकता के बिना किया जा सकता है या तुलना करने के लिए निर्देश धारा में एक शाब्दिक के रूप में।

अधिकांश प्रोसेसर के लिए सस्ती तुलना में हस्ताक्षर किए गए 0 से कम हैं, और 0. के बराबर हैं (0 से अधिक हस्ताक्षर किए गए और 0 के बराबर नहीं इन दोनों द्वारा निहित हैं)

चूँकि सभी संभावित मूल्यों में से 1 मान को खराब या असिंचित के रूप में आरक्षित करने की आवश्यकता है, तो आप इसे वही बना सकते हैं, जिसमें खराब मूल्य के लिए सबसे सस्ता परीक्षण है। यह '' 0 '' समाप्त वर्ण तार के लिए भी सही है।

यदि आप इस उद्देश्य के लिए 0 से अधिक या कम उपयोग करने की कोशिश कर रहे थे तो आप अपने पते की सीमा को आधे में काट लेंगे।


-2

निरंतर 0के बजाय प्रयोग किया जाता है NULL, क्योंकि सी साल पहले के कुछ cavemen के अरबों द्वारा किया गया था, NULL, NIL, ZIP, या NADDAकी तुलना में सभी बनाया भी बहुत कुछ समझ में होता है 0

लेकिन जब से मेमोरी एड्रेसिंग 0 से शुरू होती है, क्या 0 किसी अन्य के समान वैध एड्रेस नहीं है?

वास्तव में। हालाँकि बहुत सारे ऑपरेटिंग सिस्टम आपको एड्रेस ज़ीरो पर कुछ भी मैप करने से मना कर देते हैं, यहाँ तक कि वर्चुअल एड्रेस स्पेस में भी (लोगों को एहसास हुआ कि C एक असुरक्षित भाषा है, और यह दर्शाता है कि अशक्त सूचक डेरेक्शन बग बहुत आम हैं, उन्हें हटाने के लिए उन्हें "ठीक" करने का निर्णय लिया गया) यूज़र्सस्पेस कोड को पेज 0 पर मैप करने के लिए; इस प्रकार, यदि आप कॉलबैक कहते हैं, लेकिन कॉलबैक पॉइंटर NULL है, तो आप कुछ मनमाने कोड को निष्पादित नहीं करेंगे)।

यदि यह है तो अशक्त बिंदुओं को संभालने के लिए 0 का उपयोग कैसे किया जा सकता है?

क्योंकि 0एक पॉइंटर की तुलना में इसका उपयोग कुछ कार्यान्वयन विशिष्ट मूल्य के साथ किया जाएगा , जो कि मॉलोक विफलता पर मॉलॉक का वापसी मूल्य है।

इसके बजाय एक नकारात्मक संख्या शून्य क्यों नहीं है?

यह और भी भ्रामक होगा।


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

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

-4

( कृपया पोस्ट पढ़ने से पहले इस पैरा पढ़ेंमैं किसी को भी इस पोस्ट को पढ़ने में दिलचस्पी लेने के लिए कह रहा हूं, इसे ध्यान से पढ़ने की कोशिश करनी चाहिए, और जब तक आप इसे पूरी तरह से समझ नहीं लेते, तब तक इसे कम न करें, धन्यवाद। )

यह अब सामुदायिक विकी है, जैसे कि अगर कोई किसी भी अवधारणा से असहमत है, तो कृपया इसे संशोधित करें और स्पष्ट और विस्तृत विवरण के साथ कि क्या गलत है और क्यों, और यदि संभव हो तो कृपया स्रोतों का हवाला दें या सबूत दें जो पुन: प्रस्तुत किया जा सकता है।

उत्तर

यहाँ कुछ अन्य कारण हैं जो NULL == 0 के लिए अंतर्निहित कारक हो सकते हैं

  1. यह तथ्य कि शून्य झूठा है, इसलिए व्यक्ति if(!my_ptr)इसके बजाय सीधे कर सकता है if(my_ptr==NULL)
  2. तथ्य यह है कि uninitiated वैश्विक पूर्णांक सभी शून्य के लिए डिफ़ॉल्ट रूप से आरंभीकृत होते हैं, और सभी शून्य के इस तरह के एक सूचक को निर्विवाद माना जाएगा।

यहाँ मैं अन्य उत्तरों पर एक शब्द कहना चाहूंगा

सिंथेटिक शुगर के कारण नहीं

यह कहना कि न्यूट्रीशनल शुगर की वजह से NULL शून्य है, बहुत ज्यादा मतलब नहीं है, अगर ऐसा है तो लंबाई रखने के लिए किसी सरणी के इंडेक्स 0 का उपयोग क्यों न करें?

वास्तव में C वह भाषा है जो आंतरिक क्रियान्वयन से बहुत निकट से मिलती है, क्या यह कहने का मतलब है कि C केवल संश्लिष्ट चीनी के कारण शून्य को चुना है? वे शून्य से मैप करने के बजाय एक कीवर्ड शून्य (जैसा कि कई अन्य भाषाएं करते हैं) प्रदान करेंगे!

आज के रूप में इस तरह के रूप में यह सिर्फ चीनी के रूप में किया जा सकता है, यह स्पष्ट है कि सी भाषा डेवलपर्स का मूल इरादा वाक्यविन्यास चीनी के लिए नहीं था, जैसा कि मैं आगे दिखाऊंगा।

1) विशिष्टता

फिर भी यह सच है कि सी विनिर्देश 0 से लगातार अशक्त सूचक (धारा 6.3.2.3) के रूप में बात करता है, और NULL को कार्यान्वयन परिभाषित (C11 विनिर्देश में धारा 7.19, और C99 विनिर्देश में 7.17) के रूप में परिभाषित करता है, तथ्य यह है कि सी के आविष्कारकों द्वारा लिखी गई पुस्तक "द सी प्रोग्रामिंग लैंग्वेज" में खंड 5.4 में कहा गया है:

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

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

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

2) सारांश

हालांकि विनिर्देश स्पष्ट रूप से यह नहीं कहता है कि शून्य पते को शून्य स्थिर से भिन्न माना जा सकता है, लेकिन यह नहीं कहता है कि ऐसा नहीं है, और तथ्य यह है कि जब शून्य-सूचक निरंतर के साथ काम करता है, तो यह दावा नहीं करता है कि यह कार्यान्वयन के रूप में परिभाषित है। NULL द्वारा परिभाषित स्थिरांक, इसके बजाय शून्य होने का दावा करता है , यह दर्शाता है कि शून्य स्थिरांक और शून्य पते के बीच अंतर हो सकता है।

(हालांकि अगर यह मामला है तो मुझे आश्चर्य होता है कि NULL को क्यों परिभाषित किया गया है, क्योंकि इस तरह के मामले में NULL भी निरंतर शून्य हो सकता है, क्योंकि कंपाइलर को वैसे भी सभी शून्य स्थिरांक को वास्तविक NULL परिभाषित में परिवर्तित करना है?)

हालाँकि मैं इसे वास्तविक कार्रवाई में नहीं देखता, और सामान्य प्लेटफार्मों में पता शून्य और स्थिर शून्य को एक ही माना जाता है, और उसी त्रुटि संदेश को फेंक देते हैं।

इसके अलावा तथ्य यह है कि आज के ऑपरेटिंग सिस्टम वास्तव में पूरे पहले पृष्ठ (0x0000 से 0xFFFF तक) को जला रहे हैं, सिर्फ C के NULL पॉइंटर के कारण शून्य पते तक पहुंचने से रोकने के लिए, ( http://en.wikipedia.org/wiki देखें) Zero_page , साथ ही साथ "Windows Via C / C ++ द्वारा Jeffrey Richter और Christophe Nasarre (Microsoft प्रेस द्वारा प्रकाशित)")।

इस प्रकार मैं किसी से भी यह दावा करने के लिए कहूंगा कि वास्तव में इसने कार्रवाई में देखा है, कृपया प्लेटफॉर्म, और संकलक को निर्दिष्ट करने के लिए, और वास्तव में उसने जो सटीक कोड किया है, (हालांकि विनिर्देश में अस्पष्ट परिभाषा के कारण [जैसा कि मैंने दिखाया है) कोई संकलक और मंच जो चाहे वह करने के लिए स्वतंत्र है)।

हालांकि यह स्पष्ट रूप से लगता है कि सी के लेखकों ने इसे ध्यान में नहीं रखा था, और वे "शून्य पते" की बात कर रहे थे, और यह कि "सी गारंटी देता है कि यह कभी भी वैध पता नहीं है", साथ ही साथ "NULL सिर्फ एक है mnemonic ", स्पष्ट रूप से दिखा रहा है कि यह मूल इरादा" वाक्यविन्यास चीनी "के लिए नहीं था।

ऑपरेटिंग सिस्टम के कारण नहीं

यह भी दावा करते हुए कि ऑपरेटिंग सिस्टम कुछ कारणों से शून्य को संबोधित करने की पहुंच से इनकार करता है:

1) जब C लिखा गया था तो इस तरह का कोई प्रतिबंध नहीं था, जैसा कि कोई इस विकिपीडिया http://en.wikipedia.org/wiki/Zero_page पर देख सकता है ।

2) तथ्य यह है कि सी कंपाइलरों ने मेमोरी एड्रेस को शून्य तक पहुँचा दिया था।

यह बेल्लाबस द्वारा निम्नलिखित पेपर से तथ्य प्रतीत होता है ( http://www.cs.bell-labs.com/who/dmr/primevalC.html )

दो संकलक विवरणों में भिन्न हैं कि वे इसके साथ कैसे सामना करते हैं। पहले एक में, एक फ़ंक्शन का नामकरण करके प्रारंभ पाया जाता है; बाद में, प्रारंभ को केवल 0. लिया जाता है। यह इंगित करता है कि पहला कंपाइलर मेमोरी मैपिंग के साथ एक मशीन होने से पहले लिखा गया था, इसलिए कार्यक्रम की उत्पत्ति स्थान 0 पर नहीं थी, जबकि दूसरे के समय तक, हमारे पास पीडीपी -11 था जो मैपिंग प्रदान करता था।

(वास्तव में आज के रूप में (जैसा कि मैंने विकिपीडिया और माइक्रोसॉफ्ट प्रेस से ऊपर संदर्भों का हवाला दिया है), शून्य पते तक पहुंच को प्रतिबंधित करने का कारण है C के NULL संकेत!

3) याद रखें कि सी का उपयोग ऑपरेटिंग सिस्टम, और यहां तक ​​कि सी कंपाइलर लिखने के लिए भी किया जाता है!

वास्तव में सी को इसके साथ UNIX ऑपरेटिंग सिस्टम लिखने के उद्देश्य से विकसित किया गया था, और इस तरह यह बिना किसी कारण के प्रतीत होता है कि उन्हें खुद को पता शून्य से प्रतिबंधित करना चाहिए।

(हार्डवेयर) कैसे कंप्यूटर हैं पर व्याख्या (शारीरिक रूप से) अभिगम संबोधन शून्य करने में सक्षम

एक और बिंदु है जिसे मैं यहाँ समझाना चाहता हूँ, यह कैसे संभव है कि पता शून्य को संदर्भित किया जाए?

एक सेकंड के लिए इसके बारे में सोचो, पते प्रोसेसर द्वारा प्राप्त किए जाते हैं, और फिर मेमोरी बस पर वोल्टेज के रूप में भेजे जाते हैं, जो तब मेमोरी सिस्टम द्वारा वास्तविक पते पर प्राप्त करने के लिए उपयोग किया जाता है, और फिर भी शून्य के पते का मतलब कोई वोल्टेज नहीं होगा , तो मेमोरी सिस्टम का भौतिक हार्डवेयर पता शून्य तक कैसे पहुंच रहा है?

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


1
मैंने आपको निराश नहीं किया, लेकिन आपकी पोस्ट में कई तथ्यात्मक गलतियाँ हैं, जैसे। ऑफसेट 0 पर भौतिक मेमोरी का उपयोग असंभव है (सभी स्विच बंद होने के कारण? वास्तव में?), 0 और निरंतर 0 विनिमेय होने (वे नहीं हो सकते हैं) और अन्य।
हस्त्कर्ण

0 और निरंतर शून्य के बारे में, मूल पुस्तक यही कहती है, और इस वास्तविक परीक्षण से पता चलता है कि क्या आपने दोनों के बीच वास्तविक अंतर पाया है? यदि हाँ, तो कौन सा संकलक और मंच? जबकि कई जवाब बताते हैं कि ऐसा अंतर है जो मैंने नहीं पाया है, और उनके पास अंतर दिखाने के लिए कोई संदर्भ नहीं है। वास्तव में en.wikipedia.org/wiki/Zero_page और जेफरी रिक्टर और क्रिस्टोफ़ नसार्रे (Microsoft प्रेस द्वारा प्रकाशित) द्वारा "विंडोज़ वाया C / C ++" के अनुसार, पहला पहला पृष्ठ! आधुनिक कंप्यूटर में केवल नल से बचने के लिए संरक्षित है (वास्तव में एक से अधिक बाइट बर्बाद कर रहे हैं!)
योएल हलब

बेशक पता के बिट पैटर्न का उपयोग पढ़ने के लिए किया जा रहा है। यह आमतौर पर मामला है। किसी भी तरह, मैं आपके साथ बहस नहीं करना चाहता, मैं सिर्फ इशारा कर रहा था कि आपको क्यों उखाड़ा जा सकता है।
१२:४६ में हस्त्कर्ण

मैं आपके दावों से सहमत नहीं हूं। मुझे इस चर्चा को जारी रखने में कोई दिलचस्पी नहीं है।
Hasturkun

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