C में शून्य का अर्थ शून्य क्यों नहीं है?


25

जावा और सी #, void(या Void) जैसी दृढ़ता से टाइप की जाने वाली भाषाओं में एक विधि के लिए वापसी प्रकार का अर्थ लगता है:

यह विधि कुछ भी वापस नहीं करती है। कुछ भी तो नहीं। वापसी नहीं। आपको इस विधि से कुछ भी प्राप्त नहीं होगा।

क्या वास्तव में अजीब है कि सी में, voidवापसी प्रकार के रूप में या यहां तक ​​कि एक विधि पैरामीटर प्रकार के रूप में इसका मतलब है:

यह वास्तव में कुछ भी हो सकता है। यह जानने के लिए आपको स्रोत कोड पढ़ना होगा। सौभाग्य। यदि यह एक सूचक है, तो आपको वास्तव में पता होना चाहिए कि आप क्या कर रहे हैं।

सी में निम्नलिखित उदाहरणों पर विचार करें:

void describe(void *thing)
{
    Object *obj = thing;
    printf("%s.\n", obj->description);
}

void *move(void *location, Direction direction)
{
    void *next = NULL;

    // logic!

    return next;
}

जाहिर है, दूसरा तरीका एक पॉइंटर लौटाता है, जो परिभाषा के अनुसार कुछ भी हो सकता है।

चूँकि C, Java और C # से पुराना है, इसलिए इन भाषाओं ने void"कुछ भी नहीं" अर्थ के रूप में अपनाया, जबकि C ने इसे "कुछ नहीं या कुछ भी नहीं (जब एक पॉइंटर)" के रूप में इस्तेमाल किया।


138
आपका प्रश्न शीर्षक और पाठ के बारे में बात करता है voidजबकि कोड उदाहरण का उपयोग करता है void*जो कुछ पूरी तरह से अलग है।

4
यह भी ध्यान दें कि जावा और सी # में एक ही अवधारणा है, वे इसे केवल Objectएक मामले में खंडन करने के लिए कहते हैं।
मूइंग डक

4
@ क्यों वे बिल्कुल दृढ़ता से टाइप नहीं हैं? C # का उपयोग करके duck टाइपिंग, क्या आपका मतलब उस dynamicप्रकार से है जिसका उपयोग शायद ही कभी किया जाता है?
Axarydax

9
@ मीफे: पिछली बार जब मैंने विकिपीडिया को ग्यारह परस्पर विरोधी विरोधाभासी सूचीबद्ध किया था , "जोरदार टाइप" के लिए। यह कहना कि "C # दृढ़ता से टाइप नहीं किया गया है" इसलिए अर्थहीन है।
एरिक लिपर्ट

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

जवाबों:


58

voidउन भाषाओं में कीवर्ड (सूचक नहीं) का अर्थ "कुछ नहीं" है। यह सुसंगत है।

जैसा कि आपने उल्लेख किया है, का void*मतलब है कि "पॉइंटर टू एनीथ" भाषाओं में जो कच्चे पॉइंटर्स (सी और सी ++) का समर्थन करते हैं। यह एक दुर्भाग्यपूर्ण निर्णय है क्योंकि जैसा कि आपने उल्लेख किया है, voidइसका मतलब दो अलग-अलग चीजों से है।

मैं voidअलग-अलग संदर्भों में "कुछ भी नहीं" और "कुछ भी" का पुन: उपयोग करने के पीछे के ऐतिहासिक कारण को खोजने में सक्षम नहीं हूं , हालांकि सी कई अन्य जगहों पर ऐसा करता है। उदाहरण के लिए, staticअलग-अलग संदर्भों में अलग-अलग उद्देश्य हैं। इस तरह से कीवर्ड का पुन: उपयोग करने के लिए सी भाषा में स्पष्ट रूप से मिसाल है, इस बात की परवाह किए बिना कि कोई अभ्यास के बारे में क्या सोच सकता है।

इन मुद्दों में से कुछ को सही करने के लिए क्लीन ब्रेक बनाने के लिए जावा और सी # अलग-अलग हैं। जावा और "सुरक्षित" सी # भी कच्चे संकेत की अनुमति नहीं है और आसान सी अनुकूलता की जरूरत नहीं है (असुरक्षित सी # करता संकेत देता है, लेकिन सी # कोड के विशाल बहुमत इस श्रेणी में आते नहीं है)। यह उन्हें पीछे की संगतता के बारे में चिंता किए बिना चीजों को थोड़ा बदलने की अनुमति देता है। ऐसा करने का एक तरीका Objectपदानुक्रम की जड़ में एक वर्ग शुरू कर रहा है जिसमें से सभी कक्षाएं विरासत में मिलती हैं, इसलिए एक Objectसंदर्भ void*प्रकार के मुद्दों और कच्चे स्मृति प्रबंधन की गंभीरता के बिना एक ही कार्य करता है ।


2
जब मैं घर

4
They also do not allow raw pointers and do not need easy C compatibility.असत्य। सी # में संकेत हैं। वे आम तौर पर (और आमतौर पर होना चाहिए) बंद, लेकिन वे वहाँ हैं।
मैगस

8
क्यों वे पुन void: उपयोग के बारे में : एक स्पष्ट कारण एक नया कीवर्ड (और संभावित रूप से मौजूदा कार्यक्रमों को तोड़ना) शुरू करने से बचना होगा। यदि उन्होंने एक विशेष कीवर्ड (जैसे unknown) पेश किया था , तो void*एक अर्थहीन (और संभवतः अवैध) निर्माण unknownहोगा , और केवल के रूप में कानूनी होगा unknown*
jamesdlin

20
यहां तक ​​कि void *, void"कुछ भी नहीं" का अर्थ है, "कुछ भी नहीं"। आप किसी और को नहीं कर सकते void *, आपको इसे पहले किसी दूसरे पॉइंटर टाइप पर डालना होगा।
oefe

2
@ मुझे लगता है कि उस बाल को विभाजित करना व्यर्थ है, क्योंकि voidऔर void*विभिन्न प्रकार के होते हैं (वास्तव में, void"कोई प्रकार नहीं")। यह कहते हुए बहुत भावना के रूप में बनाता है " intमें int*साधन कुछ।" नहीं, एक बार जब आप एक पॉइंटर वैरिएबल घोषित करते हैं, तो आप कह रहे हैं "यह एक मेमोरी एड्रेस है जो कुछ रखने में सक्षम है।" के मामले में void*, आप कह रहे हैं "यह पता कुछ रखता है लेकिन सूचक के प्रकार से कुछ का अनुमान नहीं लगाया जा सकता है।"

32

voidऔर void*दो अलग चीजें हैं। voidसी में इसका मतलब बिल्कुल वैसा ही है जैसा कि जावा में होता है, रिटर्न वैल्यू का अभाव। A void*एक प्रकार की अनुपस्थिति के साथ एक संकेतक है।

C के सभी पॉइंटर्स को डिरेल करने में सक्षम होने की आवश्यकता है। यदि आप एक की अवहेलना करते हैं void*, तो आप किस प्रकार की उम्मीद करेंगे? याद रखें कि सी पॉइंटर्स किसी भी रनटाइम प्रकार की जानकारी नहीं रखते हैं, इसलिए टाइप को संकलन समय पर अवश्य जाना चाहिए।

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


1
मैं सहमत हूँ जब तक कि आप "इसे अनदेखा" न करें। यह संभव है कि लौटाई गई चीज़ में इसकी व्याख्या करने के तरीके के बारे में जानकारी हो। दूसरे शब्दों में, यह एक मूल भिन्न का C समतुल्य हो सकता है। "जब आप इसे प्राप्त करते हैं, तो यह जानने के लिए एक नज़र डालें कि यह क्या है - मैं आपको सामने नहीं बता सकता कि आप क्या पाएंगे"।
फ्लोरिस

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

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

4
@RobertHarvey हाँ, लेकिन तब आप एक शून्य पॉइंटर को डीफ़र करना नहीं कर रहे हैं; आप एक पॉइंटर पॉइंटर को शून्य पॉइंटर कास्ट कर रहे हैं और फिर डी पॉइंटर को डीफ्रॉफेंस कर रहे हैं।
user253751

4
@ फ़्लोरिस आपसे gccअसहमत हैं। यदि आप मान का उपयोग करने का प्रयास करते हैं, तो gccएक त्रुटि संदेश कहते हैं error: void value not ignored as it ought to be
कैस्परड

19

शायद यह voidरिटर्न प्रकार के रूप में सोचने के लिए अधिक उपयोगी होगा । तब आपकी दूसरी विधि "एक ऐसी विधि को पढ़ेगी जो एक बिना संकेत के सूचक को लौटाती है।"


यह सहायता करता है। जैसा कि कोई है जो (अंत में!) ऑब्जेक्ट-ओरिएंटेड भाषाओं में बिताए गए वर्षों के बाद सी सीख रहा है, संकेत कुछ ऐसा है जो मेरे लिए एक बहुत नई अवधारणा है। ऐसा लगता है कि जब कोई पॉइंटर लौटाता है, voidतो मोटे तौर पर *एक्शनस्क्रिप्ट 3 जैसी भाषाओं के बराबर होता है , जिसका सीधा सा मतलब है "कोई भी रिटर्न टाइप।"
नत्फ़ुली के

5
खैर, voidवाइल्डकार्ड नहीं है। एक सूचक केवल एक स्मृति पता है। एक प्रकार *कहते हैं इससे पहले "यहाँ डेटा प्रकार है जिसे आप इस पॉइंटर द्वारा संदर्भित मेमोरी एड्रेस पर खोजने की उम्मीद कर सकते हैं।" लाना voidपहले *संकलक करने के लिए कहते हैं, "मैं प्रकार पता नहीं है, बस मुझे कच्चे सूचक लौटने के लिए, और मैं पता लगा लेंगे कि कौन सा डेटा है कि यह की ओर इशारा से कोई लेना देना।"
रॉबर्ट हार्वे

2
मैं यह भी कहूंगा कि void*"शून्य" पर एक अंक। एक नंगे सूचक के साथ यह कुछ भी नहीं है। फिर भी आप इसे किसी अन्य पॉइंटर की तरह कास्ट कर सकते हैं।
रॉबर्ट

11

चलो शब्दावली को थोड़ा कस दें।

से ऑनलाइन सी 2011 मानक :

6.2.5 प्रकार
...
19 voidप्रकार में मूल्यों का एक खाली सेट शामिल है; यह एक अपूर्ण वस्तु प्रकार है जिसे पूरा नहीं किया जा सकता है।
...
६.३ रूपांतरण
...
६.३.२.२ शून्य

१ (कोई भी नहीं) एक voidअभिव्यक्ति का मूल्य (एक प्रकार का अभिव्यक्ति void) का किसी भी तरह से उपयोग नहीं किया जाएगा, और निहित या स्पष्ट रूपांतरण (को छोड़कर void) को लागू नहीं किया जाएगा। ऐसी अभिव्यक्ति। यदि किसी अन्य प्रकार की अभिव्यक्ति का मूल्यांकन void अभिव्यक्ति के रूप में किया जाता है , तो इसके मूल्य या डिज़ाइनर को छोड़ दिया जाता है। (एक voidअभिव्यक्ति को इसके दुष्प्रभावों के लिए मूल्यांकन किया गया है।)

6.3.2.3 पॉइंटर्स

1 ए पॉइंटर टूvoidएक सूचक से किसी भी वस्तु प्रकार में परिवर्तित किया जा सकता है। किसी भी ऑब्जेक्ट प्रकार के लिए एक पॉइंटर को शून्य और फिर से वापस करने के लिए एक पॉइंटर में परिवर्तित किया जा सकता है; परिणाम मूल सूचक के बराबर होगा।

एक voidअभिव्यक्ति का कोई मूल्य नहीं है (हालांकि इसके दुष्प्रभाव हो सकते हैं)। अगर मेरे पास लौटने के लिए कोई फ़ंक्शन परिभाषित है void, जैसे:

void foo( void ) { ... }

फिर कॉल करें

foo();

एक मूल्य का मूल्यांकन नहीं करता है; मैं परिणाम को कुछ भी नहीं बता सकता, क्योंकि कोई परिणाम नहीं है।

एक सूचक को voidअनिवार्य रूप से एक "सामान्य" सूचक प्रकार है; आप void *एक स्पष्ट कलाकारों की आवश्यकता के बिना किसी भी अन्य ऑब्जेक्ट पॉइंटर प्रकार का मान असाइन कर सकते हैं (यही कारण है कि सभी सी प्रोग्रामर आप पर परिणाम डालने के लिए चिल्लाएंगे malloc)।

आप सीधे तौर पर किसी का विरोध नहीं कर सकते void *; पॉइंट-टू ऑब्जेक्ट को एक्सेस करने से पहले आपको पहले इसे एक अलग ऑब्जेक्ट पॉइंटर टाइप पर असाइन करना होगा।

voidसंकेत (अधिक-या-कम) सामान्य इंटरफेस को लागू करने के लिए उपयोग किया जाता है; विहित उदाहरण qsortलाइब्रेरी फ़ंक्शन है, जो किसी भी प्रकार के सरणियों को सॉर्ट कर सकता है, जब तक आप एक प्रकार-जागरूक तुलना फ़ंक्शन प्रदान करते हैं।

हां, दो अलग-अलग अवधारणाओं के लिए एक ही कीवर्ड का उपयोग करना (कोई मूल्य बनाम जेनेरिक पॉइंटर) भ्रामक है, लेकिन ऐसा नहीं है कि मिसाल नहीं है; staticC और C ++ दोनों में कई अलग-अलग अर्थ हैं।


9

जावा और C # में, विधि के लिए वापसी प्रकार के रूप में शून्य का अर्थ लगता है: यह विधि कुछ भी वापस नहीं करती है। कुछ भी तो नहीं। वापसी नहीं। आपको इस विधि से कुछ भी प्राप्त नहीं होगा।

वह कथन सही है। यह C और C ++ के लिए भी सही है।

सी में, वापसी प्रकार के रूप में या यहां तक ​​कि एक विधि पैरामीटर प्रकार के रूप में शून्य का मतलब कुछ अलग है।

वह कथन गलत है। voidC या C ++ में वापसी प्रकार के रूप में इसका मतलब वही है जो यह C # और जावा में करता है। आप भ्रमित कर रहे हैं voidके साथ void*वे पूरी तरह से अलग हैं।

क्या यह भ्रामक नहीं है voidऔर void*दो पूरी तरह से अलग चीजों का मतलब है?

हां।

पॉइंटर क्या है? एक शून्य सूचक क्या है?

एक पॉइंटर एक मान होता है, जिसे डिरेल किया जा सकता है । एक अपसंदर्भन मान्य सूचक एक देता भंडारण स्थान की टाइप करने के लिए उठाई- । एक शून्य पॉइंटर एक पॉइंटर होता है, जिसमें कोई विशेष इंगित-प्रकार नहीं होता है; यह होना चाहिए परिवर्तित एक अधिक विशिष्ट सूचक प्रकार से पहले मूल्य है dereferenced एक निर्माण करने के लिए भंडारण स्थान

क्या शून्य बिंदु C, C ++, Java और C # में समान हैं?

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

चूँकि C, Java और C # से पुराना है, इसलिए इन भाषाओं ने शून्य को "कुछ भी नहीं" के रूप में अपनाया, जबकि C ने इसे "कुछ नहीं या कुछ भी नहीं (जब एक पॉइंटर)" के रूप में इस्तेमाल किया।

यह प्रश्न असंगत है क्योंकि यह असत्य की व्याख्या करता है। आइए कुछ बेहतर सवाल पूछें।

जावा और सी # ने उस कन्वेंशन को क्यों अपनाया जो voidएक वैध रिटर्न प्रकार है, उदाहरण के लिए, विज़ुअल बेसिक कन्वेंशन का उपयोग करके जो फ़ंक्शन कभी भी शून्य नहीं होते हैं और सबरूटीन हमेशा शून्य रिटर्न होते हैं?

जावा या C # भाषा में आने वाले प्रोग्रामर्स से परिचित होना जहाँ voidवापसी का प्रकार है।

C # ने भ्रमित करने वाले सम्मेलन को क्यों अपनाया, void*जिसका अर्थ पूरी तरह से अलग है void?

उन प्रोग्रामरों से परिचित होना जो C # उन भाषाओं से आते हैं जहां void*एक पॉइंटर टाइप है।


5
void describe(void *thing);
void *move(void *location, Direction direction);

पहला फ़ंक्शन कुछ भी नहीं देता है। दूसरा फ़ंक्शन एक शून्य पॉइंटर देता है। मैंने उस दूसरे कार्य को घोषित किया होगा

void* move(void* location, Direction direction);

यदि आप "शून्य" को "अर्थ के बिना" अर्थ के रूप में सोचते हैं तो मदद मिल सकती है। का वापसी मूल्य describe"बिना मतलब" है। ऐसे फ़ंक्शन से मान वापस करना गैरकानूनी है क्योंकि आपने संकलक को बताया था कि वापसी मूल्य अर्थ के बिना है। आप उस फ़ंक्शन से रिटर्न वैल्यू पर कब्जा नहीं कर सकते क्योंकि यह बिना अर्थ के है। आप voidबिना मतलब के परिवर्तनशील घोषित नहीं कर सकते । उदाहरण के लिए void nonsense;बकवास है और वास्तव में अवैध है। यह भी ध्यान दें कि शून्य की एक सरणी void void_array[42];भी बकवास है।

शून्य ( void*) के लिए एक सूचक कुछ अलग है। यह एक सूचक है, एक सरणी नहीं है। void*अर्थ के रूप में एक संकेतक पढ़ें जो "अर्थ के बिना" कुछ को इंगित करता है। सूचक "बिना मतलब का" है, जिसका अर्थ है कि इस तरह के एक सूचक को निष्क्रिय करने का कोई मतलब नहीं है। ऐसा करने की कोशिश वास्तव में गैरकानूनी है। कोड है कि एक शून्य सूचक संकलित नहीं करेंगे।

इसलिए यदि आप एक शून्य पॉइंटर को रोक नहीं सकते हैं, और आप ऐरो की एक सरणी नहीं बना सकते हैं, तो आप उनका उपयोग कैसे कर सकते हैं? इसका उत्तर यह है कि किसी भी प्रकार के एक पॉइंटर को और उसके पास डाला जा सकता है void*। कुछ पॉइंटर को किसी पॉइंटर पर रखने void*और वापस ओरिजिनल टाइप करने के लिए कास्टिंग करने से ओरिजिनल पॉइंटर के बराबर वैल्यू मिलेगी। सी मानक इस व्यवहार की गारंटी देता है। C में बहुत सारे शून्य बिंदुओं को देखने का प्राथमिक कारण यह है कि यह क्षमता एक गैर-ऑब्जेक्ट ओरिएंटेड भाषा में सूचना छिपाने और ऑब्जेक्ट-आधारित प्रोग्रामिंग को लागू करने का एक तरीका प्रदान करती है।

अंत में, कारण जो आप अक्सर moveघोषित करते हैं, void *move(...)बल्कि void* move(...)इसलिए कि सी के नाम के आगे तारांकन चिह्न लगाते हैं, सी में एक बहुत ही सामान्य अभ्यास है। कारण यह है कि निम्नलिखित घोषणा आपको बड़ी परेशानी में डाल int* iptr, jptr;देगी : यह आपको बना देगा लगता है कि आप एक को दो संकेत की घोषणा कर रहे हैं int। तुम नहीं हो। यह घोषणा करता है jptrएक intएक के बजाय एक सूचक int। उचित घोषणा यह है कि int *iptr, *jptr;आप दिखावा कर सकते हैं तारांकन चिह्न उस प्रकार के साथ है यदि आप प्रति घोषित कथन केवल एक चर घोषित करने के अभ्यास से चिपके रहते हैं। लेकिन ध्यान रहे कि आप दिखावा कर रहे हैं।


"कोड जो कि एक शून्य सूचक को संकलित करते हैं, संकलन नहीं करेंगे।" मुझे लगता है कि आप कोड का मतलब है कि एक शून्य सूचक संकलित नहीं होगा। संकलक आपको अशक्त सूचक को डीफ़रिंग करने से बचाता नहीं है; यह एक रनटाइम समस्या है।
कॉडी ग्रे

@ कोडीग्रे - धन्यवाद! तय किया कि कोड जो डेरेफेर करते हैं एक अशक्त सूचक संकलित करेंगे (इसलिए जब तक कि सूचक नहीं है void* null_ptr = 0;)।
डेविड हैमेन

2

सीधे शब्दों में कहें, तो कोई अंतर नहीं है । मैं आपको कुछ उदाहरण देता हूँ।

कहो कि मेरे पास एक वर्ग है जिसे कार कहा जाता है।

Car obj = anotherCar; // obj is now of type Car
Car* obj = new Car(); // obj is now a pointer of type Car
void obj = 0; // obj has no type
void* = new Car(); // obj is a pointer with no type

मेरा मानना ​​है कि यहाँ भ्रम यह है कि आप voidबनाम कैसे परिभाषित करेंगे void*। एक वापसी प्रकार का voidअर्थ है "मैं कुछ भी नहीं लौटाता हूं", जबकि एक वापसी प्रकार का void*अर्थ है "मैं कुछ भी नहीं का सूचक लौटाता हूं"।

यह इस तथ्य के कारण है कि एक सूचक एक विशेष मामला है। एक पॉइंटर ऑब्जेक्ट हमेशा मेमोरी में एक स्थान को इंगित करेगा, चाहे वहां कोई वैध ऑब्जेक्ट हो या नहीं। क्या मेरे void* carसंदर्भ एक बाइट, एक शब्द, एक कार, या एक साइकिल से कोई फर्क नहीं पड़ता क्योंकि मेरे void*अंक बिना किसी परिभाषित प्रकार के साथ कुछ करने के लिए । इसे परिभाषित करना बाद में हमारे ऊपर है।

C # और Java जैसी भाषाओं में, मेमोरी का प्रबंधन किया जाता है और पॉइंटर्स की अवधारणा को ऑब्जेक्ट क्लास में रोल किया जाता है। एक प्रकार की वस्तु "कुछ भी नहीं" के संदर्भ के बजाय हम जानते हैं कि बहुत कम से कम हमारी वस्तु "वस्तु" प्रकार की है। मुझे क्यों समझाते हैं।

पारंपरिक C / C ++ में यदि आप एक ऑब्जेक्ट बनाते हैं और उसके पॉइंटर को हटाते हैं, तो उस ऑब्जेक्ट तक पहुंच प्राप्त करना असंभव है। यह वही है जिसे मेमोरी लीक के रूप में जाना जाता है ।

C # / Java में, सब कुछ एक ऑब्जेक्ट है और यह रनटाइम को हर ऑब्जेक्ट का ट्रैक रखने में सक्षम बनाता है। यह जानना जरूरी नहीं है कि मेरी वस्तु एक कार है, इसे बस कुछ बुनियादी जानकारी जानने की जरूरत है जो पहले से ही वस्तु वर्ग द्वारा ध्यान रखा गया है।

हमारे लिए प्रोग्रामर, इसका मतलब यह है कि हमें सी / सी ++ की मैन्युअल रूप से देखभाल करने के लिए बहुत सी जानकारी ऑब्जेक्ट क्लास द्वारा हमारे लिए ध्यान रखी जाती है, जो कि विशेष मामले की आवश्यकता को दूर करता है जो कि पॉइंटर है।


"मेरा शून्य * बिना किसी परिभाषित प्रकार के किसी चीज़ की ओर इशारा करता है" - बिल्कुल नहीं। यह कहना अधिक सही है कि यह शून्य-लंबाई मान के लिए एक संकेतक है (लगभग 0 तत्वों के साथ एक सरणी की तरह, लेकिन सरणी से जुड़ी जानकारी के बिना भी)।
स्कॉट व्हिटलॉक

2

मैं यह कहने की कोशिश करूंगा कि कोई इन चीजों के बारे में सी में कैसे सोच सकता है। सी मानक में आधिकारिक भाषा वास्तव में कम से कम नहीं है void , और मैं पूरी तरह से इसके अनुरूप होने की कोशिश नहीं करूंगा।

प्रकारों voidमें प्रथम श्रेणी का नागरिक नहीं है। हालाँकि यह एक ऑब्जेक्ट प्रकार है, यह किसी भी ऑब्जेक्ट (या मान), फ़ील्ड का या फ़ंक्शन पैरामीटर का प्रकार नहीं हो सकता है; हालाँकि, यह एक फ़ंक्शन का रिटर्न प्रकार हो सकता है, और इस प्रकार एक अभिव्यक्ति का प्रकार हो सकता है (मूल रूप से ऐसे कार्यों के कॉल, लेकिन सशर्त ऑपरेटर के साथ गठित अभिव्यक्ति भी शून्य प्रकार हो सकती है)। लेकिन voidएक मूल्य प्रकार के रूप में भी कम से कम उपयोग, जो ऊपर के दरवाजे को खुला छोड़ देता है, अर्थात् एक फ़ंक्शन को समाप्त करने voidके लिए फॉर्म का एक बयान return E;जहां Eप्रकार की अभिव्यक्ति है void, सी में स्पष्ट रूप से मना किया गया है (यह C ++ में अनुमत है, हालांकि, लेकिन C पर लागू नहीं होने वाले कारणों के लिए)।

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

मूल्य प्रकार के रूप में अस्वीकृत होने के कारण, void"निषिद्ध" को नामित करने के लिए कम से कम दो सीधे संबंधित तरीकों का उपयोग नहीं किया गया है: (void)फ़ंक्शन प्रकारों में पैरामीटर विनिर्देश के रूप में निर्दिष्ट करने का अर्थ है कि उन्हें कोई तर्क प्रदान करना निषिद्ध है (जबकि () 'इसके विपरीत सब कुछ होगा। अनुमति है, और हाँ, यहां तक ​​कि पैरामीटर विनिर्देश के voidसाथ कार्यों के लिए तर्क के रूप में एक अभिव्यक्ति प्रदान (void)करना निषिद्ध है), और घोषित करने का void *pमतलब है कि डेरेफेरिंग अभिव्यक्ति *pनिषिद्ध है (लेकिन यह नहीं है कि यह एक प्रकार की वैध अभिव्यक्ति है void)। तो आप सही हैं कि ये उपयोग voidवास्तव में संगत नहीं हैंvoid में एक मान्य प्रकार के अभिव्यक्तियों के । हालाँकि एक प्रकार की वस्तुvoid*वास्तव में किसी भी प्रकार के मूल्यों के लिए एक संकेतक नहीं है, इसका मतलब है कि एक ऐसा मान है जो एक पॉइंटर के रूप में माना जाता है, हालांकि इसे निष्क्रिय नहीं किया जा सकता है और इसके साथ सूचक अंकगणित करने के लिए निषिद्ध है। "एक पॉइंटर के रूप में माना जाता है" तो वास्तव में केवल इसका मतलब है कि इसे बिना किसी जानकारी के नुकसान के बिना किसी भी पॉइंटर प्रकार से डाला जा सकता है। हालाँकि, इसका उपयोग पूर्णांक मानों को और इससे भी करने के लिए किया जा सकता है, इसलिए इसका किसी भी चीज़ की ओर संकेत नहीं होता है।


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

0

C # और Java में, हर क्लास एक Objectक्लास से ली गई है । इसलिए जब भी हम "कुछ" के संदर्भ को पास करना चाहते हैं, तो हम प्रकार के संदर्भ का उपयोग कर सकते हैं Object

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


0

सी में, किसी भी प्रकार की चीजों के लिए सूचक होना संभव है [संकेत एक प्रकार का संदर्भ है]। एक पॉइंटर किसी ज्ञात प्रकार के ऑब्जेक्ट की पहचान कर सकता है, या यह अनियंत्रित (अज्ञात) प्रकार के ऑब्जेक्ट की पहचान कर सकता है। C के रचनाकारों ने "सूचक को मनमाने प्रकार की चीज के लिए" के समान सामान्य वाक्यविन्यास का उपयोग करने के लिए चुना "कुछ विशेष प्रकार की चीज के लिए सूचक" के रूप में। चूंकि बाद वाले मामले में सिंटैक्स को यह निर्दिष्ट करने के लिए एक टोकन की आवश्यकता होती है कि प्रकार क्या है, पूर्व सिंटैक्स को कुछ ऐसा डालने की आवश्यकता होती है जहां टाइप ज्ञात होने पर उस टोकन का संबंध होगा। C ने उस उद्देश्य के लिए "void" कीवर्ड का उपयोग करना चुना।

पास्कल में, सी के साथ के रूप में, किसी भी प्रकार की चीजों को इंगित करना संभव है; पास्कल की अधिक लोकप्रिय बोलियाँ भी "सूचक को मनमाने प्रकार की चीज़" की अनुमति देती हैं, लेकिन उसी वाक्यविन्यास का उपयोग करने के बजाय जैसा कि वे "सूचक को किसी विशेष प्रकार की चीज़ के लिए" का उपयोग करते हैं, वे बस पूर्व के रूप में संदर्भित करते हैं Pointer

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

void*मनमाने ढंग से कुछ करने के लिए एक सूचक के रूप में नामकरण का उपयोग अभी तक है, क्योंकि मैं सी को अद्वितीय और सी + + जैसे प्रत्यक्ष डेरिवेटिव को जानता हूं; अन्य भाषाओं को मैं केवल एक विशिष्ट प्रकार के नाम का उपयोग करके अवधारणा को संभालना जानता हूं।


-1

आप voidएक तरह के कीवर्ड के बारे में सोच सकते हैं जैसे struct( C99 में खाली संरचना स्पष्ट रूप से अस्वीकृत है । .NET और C ++ में वे 0 से अधिक मेमोरी लेते हैं, और अंतिम बार मुझे याद है कि जावा में सब कुछ एक वर्ग है):

struct void {
};

... जिसका अर्थ है कि यह 0 लंबाई के साथ एक प्रकार है। जब आप फ़ंक्शन कॉल करते हैं तो यह इसी तरह से काम करता है, जो रिटर्न देता है void... पूर्णांक रिटर्न मान के लिए स्टैक पर 4 बाइट या तो आवंटित करने के बजाय, यह स्टैक पॉइंटर को बिल्कुल नहीं बदलता है (0 की लंबाई तक बढ़ाता है) )।

इसलिए, यदि आपने कुछ चर घोषित किए हैं जैसे:

int a;
void b;
int c;

... और फिर आपने उन चरों का पता लिया, तब शायद bऔर cस्मृति में एक ही स्थान पर स्थित हो सकता है, क्योंकि bइसकी लंबाई शून्य है। तो एक void*स्मृति में एक सूचक है अंतर्निहित लंबाई के साथ निर्मित प्रकार। तथ्य यह है कि आप यह जान सकते हैं कि इसके तुरंत बाद कुछ है जो आपके लिए उपयोगी हो सकता है, यह एक और मामला है, और आपको वास्तव में यह जानने की आवश्यकता है कि आप क्या कर रहे हैं (और खतरनाक है)।


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