शून्य मुक्त मूल्य शून्य क्यों डाले?


82

मैं एक किताब पढ़ रहा हूं ( बुटेनहोफ, 1997 द्वारा पोसिक्स थ्रेड्स के साथ प्रोग्रामिंग ) जो सी का उपयोग करता है, और मैं निम्नलिखित पंक्ति में आया हूं:

(void)free(data);

यहाँ, dataएक आवंटित संरचना के लिए सिर्फ एक संकेतक है,

data = malloc(sizeof(my_struct_t));

क्यों freeडाली जा रही है void?

सी की मेरी समझ से, यह दो कारणों से समझ में नहीं आता है:

  • मुफ्त फ़ंक्शन पहले से ही वापस आ जाता है void
  • कोड रिटर्न मान का उपयोग नहीं कर रहा है (यह एक चर को भी नहीं सौंपा जा रहा है)

पुस्तक 1997 में लिखी गई थी। क्या यह किसी प्रकार की विरासत है?

लेखक का उल्लेख है कि उदाहरण डिजिटल यूनिक्स 4.0 डी पर चलाए गए थे, लेकिन मैं अभी भी एक फ़ंक्शन के परिणाम को डालने के लिए एक कारण की कल्पना नहीं कर सकता हूं यदि आप उस परिणाम का उपयोग नहीं करने जा रहे हैं।


कुछ संभावित स्पष्टीकरण यहां
देखे

3
जिज्ञासा से बाहर, आपकी सी पुस्तक के प्रकाशन की तारीख क्या है? (यह कौन सी पुस्तक है?) यदि यह 1995 से पहले की है, तो इसके लिए कुछ औचित्य हो सकता है - मानक सी कंपाइलर तब से पहले सर्वव्यापी नहीं थे। अगर यह उसके बाद प्रकाशित हुआ है और अभी भी कलाकारों (और क्यों नहीं का स्पष्टीकरण) में शामिल है, तो चिंता करें कि यह आपको कौन सी अन्य बुरी आदतें सिखा रहा है। हाल ही की एक पुस्तक प्राप्त करें!
जोनाथन लेफ्लर 21


3
@JonathanLeffler जैसा कि मेरे मूल पोस्ट में बताया गया है, पुस्तक 1997 में प्रकाशित हुई थी और UNIX 4.0d का उपयोग कर रही थी। डेविड आर। ब्यूटेनहोफ़ की पुस्तक "प्रोग्रामिंग थ्रू पोज़िक्स थ्रेड्स" है। अब तक यह बहुत जानकारीपूर्ण रहा है और पोसिक्स थ्रेड्स मानक के मूल योगदानकर्ताओं में से एक द्वारा लिखा गया है।
एडम जॉनसन

6
मैं पिछले सप्ताह की अपनी प्रति का उपयोग कर रहा हूं - हां, यह अभी भी उपयोगी है। यह ub सर्वव्यापी मानक C ’(मैंने 1995 के बारे में कहा था) के पुंज पर लिखा था। 'यूनिक्स 4.0 डी' डिजिटल यूनिक्स की तरह लगता है - यही वह जगह है जहां ब्यूटेनहोफ़ ने काम किया और प्रस्तावना में इसका उल्लेख है। free()पुस्तक में एक विषमता के रूप में कलाकारों को समझो कि आपको अनुकरण करने की आवश्यकता नहीं है। यह लंबे समय से पहले एक बार अर्ध-प्रासंगिक था, लेकिन यह किसी भी अधिक प्रासंगिक नहीं है।
जोनाथन लेफ्लर 21

जवाबों:


100

अगर हम मानक freeफ़ंक्शन के बारे में बात कर रहे हैं तो इसका प्रोटोटाइप है

void free(void *ptr);

इसलिए कास्ट पूरी तरह से बेकार है।
अब कुछ अटकलें।

लेखक stdlib.hइस प्रोटोटाइप को घोषित करने वाले हेडर को शामिल करना भूल गया होगा , इसलिए कंपाइलर इसे रिटर्न प्रकार मान रहा है int। अब इस कोड के स्थैतिक विश्लेषण के दौरान संकलक अप्रयुक्त वापसी मूल्य के बारे में चेतावनी दे रहा था कि यह एक गैर- voidफ़ंक्शन क्या समझता है । इस तरह की चेतावनियों को आमतौर पर कलाकारों को जोड़कर चुप कराया जाता है void


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

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

74

यह एक विरासत वाली बात होगी!

इससे पहले कि सी मानक था, free()फ़ंक्शन प्रकार का (अव्यवस्थित रूप से) intहोगा - क्योंकि अभी तक voidवापसी के लिए मज़बूती से एक प्रकार नहीं था । कोई मूल्य नहीं लौटाया गया था।

जब कोड को पहली बार मानक C संकलक के साथ काम करने के लिए संशोधित किया गया था, तो इसमें संभवतः शामिल नहीं था <stdlib.h>(क्योंकि यह मानक से पहले मौजूद नहीं था)। पुराने कोड आवंटन कार्यों के लिए extern char *malloc();(शायद extern) के बिना (इसी तरह calloc()और realloc()) लिखेंगे , और घोषित करने की आवश्यकता नहीं थी free()। और कोड फिर सही प्रकार पर वापसी का मूल्य डालेगा - क्योंकि यह कम से कम कुछ प्रणालियों पर आवश्यक था (मैं जिस पर सी सीखा था) सहित।

कुछ समय बाद, एक शिकायत से बचने के (void)लिए संकलक (या, अधिक संभावना है lint) को बताने के लिए कलाकारों को जोड़ा गया था कि "से वापसी मूल्य free()जानबूझकर अनदेखा किया गया है"। लेकिन बेहतर होता कि वह <stdlib.h>अपनी घोषणा को जोड़ते और extern void free(void *vp);बतातेlint या संकलक को अनदेखा करने का कोई मूल्य नहीं था।

JFTR: वापस मध्य -80 के दशक में, ICL Perq मूल रूप से एक शब्द-उन्मुख वास्तुकला पर था और char *एक मेमोरी लोकेशन के लिए पता 'कुछ भी कुछ भी' से एक ही स्थान पर एक बहुत अलग संख्या थी। char *malloc()किसी तरह घोषित करना महत्वपूर्ण था ; परिणाम को किसी अन्य पॉइंटर प्रकार से डालना महत्वपूर्ण था। सीपीयू ने वास्तव में सीपीयू द्वारा उपयोग की जाने वाली संख्या को बदल दिया। (जब हमारे सिस्टम पर मुख्य मेमोरी को 1 MiB से 2 MiB में अपग्रेड किया गया था, तो बहुत खुशी हुई - चूंकि कर्नेल का उपयोग लगभग 3/4 MiB था, इसका मतलब था कि उपयोगकर्ता प्रोग्राम पेजिंग से पहले 1 1/4 MiB का उपयोग कर सकते हैं)


9
मैंने अभी K & R, 1st संस्करण की एक प्रति खोली है, जिसमें free()p पर कार्यान्वयन है । 177 जो स्पष्ट रूप से रिटर्न करता है int
पूर्व निहिलो

9
बेशक - voidमानक जारी होने से पहले कुछ सिस्टम (यूनिक्स सिस्टम III, हो सकता है) में जोड़ा गया था, लेकिन K & R 1st Edn (1978) लिखे जाने पर C का हिस्सा नहीं था। एक फ़ंक्शन जो किसी मूल्य को वापस नहीं करता था, वह रिटर्न प्रकार के बिना घोषित किया गया था (जिसका अर्थ था कि यह वापस लौटा है int), और जब तक आप उस मूल्य का उपयोग नहीं करते जो वापस नहीं आया था, कोई समस्या नहीं थी। C90 मानक को उस तरह के कोड को वैध मानना ​​था - यह पूरी तरह से विफल हो जाता क्योंकि एक मानक ऐसा नहीं था। लेकिन C99 ने 'निहित int' और 'निहित फ़ंक्शन घोषणा' नियमों को हटा दिया । दुनिया में सभी कोड नहीं पकड़े गए हैं।
जोनाथन लेफ्लर 21

5
ओप का दावा है कि यह पुस्तक 1997 में लिखी गई थी। आप यहाँ जिस बारे में बात कर रहे हैं वह बहुत ही पूर्व-मानक "K & R C" है और यह प्रतीत नहीं होता है कि कोई भी इस बारे में एक पुस्तक लिखेगा। मेरी जानकारी में मौजूद एकमात्र ऐसी पुस्तक वास्तव में K & R 1st संस्करण थी।
लुंडिन

यह एक अक्सर (अगर क्विकोटिक) अभ्यास है जिसमें हेडर शामिल नहीं थे यदि आपको लगा कि आप अंतर्निहित घोषणा के साथ दूर हो सकते हैं, क्योंकि लोगों को लगा कि यह निर्माण समय को कम करेगा।
स्पेंसर

किसी के लिए एक (void)जाति का उपयोग करता है printf()??
लुइस कोलोराडो

11

इस कलाकारों की जरूरत नहीं है। यह शायद उस समय नहीं रहा होगा जब C को C89 के रूप में मानकीकृत किया गया था।

यदि ऐसा होता, तो यह निहित घोषणा के कारण होता । इसका आमतौर पर मतलब था कि कोड लिखने वाला व्यक्ति भूल गया #include <stdlib.h>और एक स्थिर विश्लेषक का उपयोग किया जा रहा था। यह सबसे अच्छा समाधान नहीं है और एक बेहतर विचार सिर्फ #include <stdlib.h>इसके बजाय होता। यहाँ अंतर्निहित घोषणा के बारे में C89 से कुछ शब्द हैं:

यदि फ़ंक्शन कॉल में कोष्ठक की गई तर्क सूची से पहले की अभिव्यक्ति में केवल एक पहचानकर्ता होता है, और यदि इस पहचानकर्ता के लिए कोई घोषणा दिखाई नहीं देती है, तो पहचानकर्ता को स्पष्ट रूप से घोषित किया जाता है, जैसे कि फ़ंक्शन कॉल वाले अंतरतम ब्लॉक में, घोषणा।

extern int identifier();

दिखाई दिया।

लेकिन उस क्योंकि वे का परिणाम कास्टिंग नहीं कर रहे हैं अजीब है mallocया तो, और mallocऔर freeएक ही हेडर फाइल में कर रहे हैं।

यह भी संभव है कि यह केवल एक गलती है या पाठक को बताने का कोई तरीका है जो freeकोई परिणाम नहीं देता है।


5
सिर्फ इसलिए कि एक भाषा मानकीकृत हो जाती है, इसका मतलब यह नहीं है कि हर कोई तुरन्त अपने टूलकिन और कोड को अपडेट कर सकता है। यह पुरानी शैली के "K & R" C के लिए एक और 8 वर्षों के आसपास अटक गया है। फिर भी, मैं मानता हूं कि यह अजीब है कि एक स्थैतिक विश्लेषण उपकरण के लिए कलाकारों की आवश्यकता होगी, freeलेकिन इसके लिए नहीं malloc
dan04

4
@ dan04 आप आमतौर पर मालॉक के परिणाम का उपयोग करते हैं;) मैं कंपाइलर थूकना चेतावनी को रोकने के लिए (शून्य) प्रिंटफ (...) जैसी चीजों को लिखने का प्रशंसक नहीं हूं, लेकिन "बिना किसी चेतावनी के संकलन करना चाहिए, यहां तक ​​कि बेवकूफ भी" कुछ ऐसा है बहुत सारी परियोजनाओं में होता है।
रिचार्डब
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.