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

एक अनुरूप सी कार्यान्वयन कर सकते हैं # define null कुछ निराला होना करने के लिए

मैं इस थ्रेड में उकसाया गया चर्चा के कारण पूछ रहा हूं।

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

सी मानक में NULL और निरर्थक स्थिरांक के बारे में कहने के लिए बहुमूल्य कुछ शब्द हैं। केवल दो प्रासंगिक अनुभाग हैं जो मुझे मिल सकते हैं प्रथम:

3.2.2.3 संकेतक

मान 0 के साथ एक अभिन्न निरंतर अभिव्यक्ति, या इस प्रकार एक अभिव्यक्ति को शून्य * टाइप करने के लिए डाला जाता है, जिसे शून्य सूचक स्थिरांक कहा जाता है अगर एक अशक्त सूचक स्थिरांक को एक सूचक को समानता के समान या तुलना करने के लिए निर्दिष्ट किया जाता है, तो निरंतर उस प्रकार के एक संकेतक में कनवर्ट हो जाता है। ऐसा सूचक, जिसे एक शून्य सूचक कहा जाता है, किसी भी ऑब्जेक्ट या फ़ंक्शन के लिए सूचक से असमान की तुलना करने के लिए गारंटी है।

और दूसरा:

4.1.5 आम परिभाषाएं

मैक्रोज़ हैं

 NULL 

जो एक कार्यान्वयन-परिभाषित नल सूचक निरंतर तक फैलता है;

प्रश्न है, क्या NULL को कार्यान्वयन-परिभाषित नल सूचक स्थिर करने के लिए विस्तारित किया जा सकता NULL जो कि 3.2.2.3 में वर्णित लोगों से अलग है?

विशेष रूप से, इसे परिभाषित किया जा सकता है:

 #define NULL __builtin_magic_null_pointer 

या और भी:

 #define NULL ((void*)-1) 

3.2.2.3 का मेरा पठन यह है कि यह निर्दिष्ट करता है कि 0 का एक अभिन्न निरंतर अभिव्यक्ति, और शून्य का टाइप करने के लिए 0 डास्ट का एक अभिन्न निरंतर अभिव्यक्ति * निरर्थक सूचक निरंतर के रूपों में से होना चाहिए, जो कि कार्यान्वयन को पहचानता है, लेकिन यह नहीं है एक व्यापक सूची होने का मतलब मेरा मानना ​​है कि कार्यान्वयन अन्य स्रोतों के निर्माण को नल सूचक स्थिरांक के रूप में पहचानने के लिए स्वतंत्र है, जब तक कि कोई अन्य नियम टूट न हो।

इसलिए उदाहरण के लिए, यह सिद्ध है कि

 #define NULL (-1) 

कानूनी परिभाषा नहीं है, क्योंकि इसमें

 if (NULL) do_stuff(); 

do_stuff() को नहीं कहा जाना चाहिए, जबकि साथ

 if (-1) do_stuff(); 

do_stuff() को बुलाया जाना चाहिए; क्योंकि वे समतुल्य हैं, यह NULL की कानूनी परिभाषा नहीं हो सकती NULL

लेकिन मानक कहता है कि पूर्णांक-टू-पॉइंटर रूपांतरण (और उपाध्यक्ष) कार्यान्वयन-परिभाषित हैं, इसलिए यह 1 के रूपांतरण को एक सूचक के रूप में परिभाषित कर सकता है, जो रूपांतरण के रूप में एक नल सूचक बनाती है। कौनसे मामलेमें

 if ((void*)-1) 

झूठी मूल्यांकन करेंगे, और सभी अच्छी तरह से होंगे

तो अन्य लोग क्या सोचते हैं?

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

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

स्टीव जेसप को पता चला कि प्रोग्राम को NULL रूप में परिभाषित नहीं किया गया है, जो 3.2.2.3 में निरर्थक पॉइंटर स्थिरांक के रूप में परिभाषित नहीं है, जो स्थिरता को मजबूत करना है:

 #define stringize_helper(x) #x #define stringize(x) stringize_helper(x) 

इस मैक्रो का उपयोग कर, एक सकता है

 puts(stringize(NULL)); 

और "पता लगाता है" कि नल 3.2.2.3 में किसी एक फार्म का विस्तार नहीं करता है। क्या अन्य परिभाषाओं को अवैध रूप से प्रस्तुत करना पर्याप्त है? मुझे अभी नहीं पता है

धन्यवाद!

वेब के समाधान से एकत्रित समाधान "एक अनुरूप सी कार्यान्वयन कर सकते हैं # define null कुछ निराला होना करने के लिए"

C99 मानक में, §7.17.3 बताता है कि NULL "किसी कार्यान्वयन के लिए निरर्थक सूचक निरंतर सूचक को बढ़ाता है" इस बीच §6.3.2.3.3 नल सूचक स्थिरांक को "मान 0 के साथ एक पूर्णांक निरंतर अभिव्यक्ति, या इस तरह के एक अभिव्यक्ति को टाइप करने के लिए void * " के रूप में परिभाषित करता है। चूंकि एक निरर्थक सूचक निरंतर के लिए कोई अन्य परिभाषा नहीं है, NULL की एक अनुकूल परिभाषा को मूल्य शून्य (या इस डाली को void * ) के साथ पूर्णांक निरंतर अभिव्यक्ति में विस्तार करना होगा।

सी एफ से पूछे जाने वाले सवाल 5.5 (जोर दिया गया) से उद्धृत:

सी स्टैंडर्ड के धारा 4.1.5 में कहा गया है कि NULL "कार्यान्वयन-परिभाषित नल पॉइंटर स्थिरांक तक फैलता है," जिसका मतलब है कि कार्यान्वयन का चयन करने के लिए 0 का उपयोग करने वाला और क्या `शून्य *` का उपयोग करना है; प्रश्न 5.6 और 5.7 देखें "कार्यान्वयन-परिभाषित" का अर्थ यह नहीं है कि शून्य कुछ कार्यान्वयन-विशिष्ट नोजरियो आंतरिक नल सूचक मान से मिलान करने के लिए # परिभाषित हो सकता है

यह सही समझ में आता है; चूंकि मानक को शून्य सूचक को निरर्थक सूचक में संकलित करने की आवश्यकता होती है (चाहे मशीन के आंतरिक प्रतिनिधित्व को शून्य मान दिया जाए या नहीं), उस स्थिति में जहां NULL को परिभाषित किया गया है, उसे किसी भी तरह से संभाला जाना चाहिए। नल संकेत प्राप्त करने के लिए प्रोग्रामर को NULL टाइप करने की आवश्यकता नहीं है; यह सिर्फ एक स्टाइलिश कन्वेंशन है (और त्रुटियों को पकड़ने में मदद कर सकता है जैसे कि जब कोई NULL परिभाषित किया जाता है (void *)0 को गैर-सूचक संदर्भ में उपयोग किया जाता है)।

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

यह अन्य उत्तरों में से कुछ पर थोड़ा फैलता है और कुछ बिंदुओं को बना देता है जो दूसरों को याद करते हैं

प्रशंसा पत्र N1570 2011 के आईएसओ सी मानक का मसौदा हैं। मेरा मानना ​​है कि इस क्षेत्र में 1989 एएनएसआई सी मानक (जो 1 99 0 आईएसओ सी मानक के बराबर है) के बाद से इस क्षेत्र में कोई भी महत्वपूर्ण बदलाव हुए हैं। "7.1 9 3" के संदर्भ में उपधारा 7.1 9, पैराग्राफ 3 का संदर्भ है। (प्रश्न में दिए गए प्रशस्तियां 1989 के एएनएसआई मानक के रूप में प्रतीत होती हैं, जिसने अनुभाग 3 में भाषा और खंड 4 में पुस्तकालय का वर्णन किया है; आईएसओ मानक के सभी संस्करण खंड 6 में भाषा का वर्णन और खंड 7 में पुस्तकालय।)

7.1 9 3 के लिए मैक्रो NULL को "एक कार्यान्वयन-परिभाषित नल सूचक स्थिर" तक विस्तृत करने की आवश्यकता है।

6.3.2.33 पीपी कहते हैं:

मान 0 के साथ एक पूर्णांक निरंतर अभिव्यक्ति, या void * को टाइप करने के लिए इस तरह के एक अभिव्यक्ति को, एक नल पॉइंटर स्थिरांक कहा जाता है

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

इसलिए यदि हम "कुछ निराला" हैं, तो हमें यह देखने की जरूरत है कि "पूर्णांक निरंतर अभिव्यक्ति" क्या हो सकता है

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

"मान 0 के साथ पूर्णांक निरंतर अभिव्यक्ति" कई चीजों में से एक हो सकती है (यदि हम क्षमता की सीमाओं की उपेक्षा करते हैं तो असीम रूप से कई)। एक शाब्दिक 0 सबसे स्पष्ट है। अन्य संभावनाएं 0x0 , 00000 , 1-1 , '\0' , और '-'-'-' । (यह 100% स्पष्ट नहीं है कि क्या "मान 0" विशेष प्रकार से टाइप int उस मान को दर्शाता है, लेकिन मुझे लगता है कि यह सहमति है कि 0L भी एक वैध नल सूचक स्थिर है।)

एक और प्रासंगिक खंड 6.6p10 है:

एक कार्यान्वयन निरंतर अभिव्यक्ति के अन्य रूपों को स्वीकार कर सकता है।

यह पूरी तरह स्पष्ट नहीं है (मेरे लिए) यह कितना अक्षांश है जिसका उद्देश्य यह अनुमति देना है उदाहरण के लिए, एक कंपाइलर एक एक्सटेंशन के रूप में बाइनरी लीटरल्स का समर्थन कर सकता है; तो 0b0 एक वैध नल सूचक स्थिर होगा। यह const ऑब्जेक्ट के लिए C ++ – शैली संदर्भों को भी अनुमति दे सकता है, ताकि दिए गए

 const int x = 0; 

x एक संदर्भ निरंतर अभिव्यक्ति हो सकता है (यह मानक सी में नहीं है)।

तो यह स्पष्ट है कि 0 एक शून्य सूचक स्थिर है, और यह NULL मैक्रो के लिए एक मान्य परिभाषा है।

यह समान रूप से स्पष्ट है कि (void*)0 एक शून्य सूचक स्थिर है, लेकिन यह 7.1.2p5 के कारण NULL लिए मान्य परिभाषा नहीं है:

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

अगर (void*)0 को (void*)0 विस्तारित किया गया है, तो sizeof NULL अभिव्यक्ति एक वाक्यविन्यास त्रुटि होगा।

तो के बारे में ((void*)0) ? ठीक है, मैं 99.9% यकीन है कि इसका मतलब है कि यह NULL लिए एक वैध परिभाषा NULL , लेकिन 6.5.1, जो कन्वाचित अभिव्यक्ति का वर्णन करता है, कहते हैं:

एक कोष्ठक अभिव्यक्ति एक प्राथमिक अभिव्यक्ति है इसका प्रकार और मूल्य अनप्रेरलाइज्ड अभिव्यक्ति के समान हैं। यह एक लावल्यू, फ़ंक्शन डिज़िनेेटर या शून्य अभिव्यक्ति है, यदि अनुप्रयक्षित अभिव्यक्ति क्रमशः, एक लावल्यू, फंक्शन डिज़िनेएटर या शून्य अभिव्यक्ति है।

यह यह नहीं कहता है कि एक कोष्ठकित नल सूचक स्थिर एक अशक्त सूचक स्थिरांक है। फिर भी, जहां तक ​​मुझे पता है कि सभी सी compilers काफी हद तक मानते हैं कि एक कोष्ठकित नल सूचक स्थिर एक अशक्त सूचक निरंतर है, ((void*)0 लिए एक वैध परिभाषा बना रही NULL

क्या होगा यदि एक शून्य सूचक को सभी-बिट्स-शून्य के रूप में नहीं दर्शाया जाता है, लेकिन कुछ अन्य बिट पैटर्न के रूप में, उदाहरण के लिए, 0xFFFFFFFF बराबर एक 0xFFFFFFFF । तब (void*)0xFFFFFFFF , भले ही यह एक अशक्त सूचक को मूल्यांकन करने के लिए होता है एक शून्य सूचक स्थिर नहीं है, बस क्योंकि यह उस शब्द की परिभाषा को संतुष्ट नहीं करता है

तो मानक द्वारा अन्य विविधताओं की अनुमति क्या है?

चूंकि कार्यान्वयन निरंतर अभिव्यक्ति के अन्य रूपों को स्वीकार कर सकता है, एक कंपाइलर __null को परिभाषित कर सकता है __null प्रकार की निरंतर अभिव्यक्ति के रूप में मान 0 , या तो __null या ((void*)__null) को NULL की परिभाषा के रूप में अनुमति देता NULL । यह खुद को सूचक प्रकार के एक निरंतर भी बना सकता है, लेकिन यह NULL की परिभाषा के रूप में __null उपयोग नहीं कर सकता, क्योंकि यह परिभाषा 6.3.2.3.33 में संतुष्ट नहीं करता है।

एक संकलक एक ही चीज़ को पूरा कर सकता है, इसमें कोई संकलक जादू नहीं है, जैसे:

 enum { __null }; #define NULL __null 

यहां __null एक पूर्णांक __null अभिव्यक्ति है, जो मान 0 साथ प्रकार के int , इसलिए इसे कहीं भी इस्तेमाल किया जा सकता है एक निरंतर 0 का उपयोग किया जा सकता है।

__null जैसे प्रतीक के रूप में NULL को परिभाषित करने वाला लाभ यह है कि संकलक एक (शायद वैकल्पिक) चेतावनी को जारी कर सकता है अगर NULL को गैर-सूचक स्थिर में उपयोग किया जाता है उदाहरण के लिए, यह:

 char c = NULL; /* PLEASE DON'T DO THIS */ 

पूरी तरह से कानूनी है अगर NULL को 0 रूप में परिभाषित किया जाए; __null जैसे कुछ पहचानने योग्य टोकन को NULL का विस्तार करना, इस संदिग्ध निर्माण का पता लगाने के लिए संकलक के लिए आसान बनाना होगा।

ठीक है, मुझे यह साबित करने का एक तरीका मिला है

 #define NULL ((void*)-1) 

नल की कानूनी परिभाषा नहीं है

 int main(void) { void (*fp)() = NULL; } 

शून्य के साथ फ़ंक्शन पॉइंटर शुरू करना कानूनी और सही है, जबकि …

 int main(void) { void (*fp)() = (void*)-1; } 

… एक बाध्यता उल्लंघन है जिसके लिए निदान की आवश्यकता होती है। तो यह बाहर है

लेकिन NULL की __builtin_magic_null_pointer परिभाषा उस समस्या से ग्रस्त नहीं होगी। मैं अभी भी जानना चाहूंगा कि कोई भी इस कारण से ऐसा क्यों नहीं हो सकता है।

बाद के वर्षों में, लेकिन कोई भी इस बिंदु को ऊपर नहीं उठाया: मान लीजिए कि कार्यान्वयन वास्तव में उपयोग करने के लिए चुनता है

 #define NULL __builtin_null 

C99 का मेरा पठन यह है कि जब तक विशेष कीवर्ड __builtin_null व्यवहार करता है, तब तक यह ठीक होता है- अगर यह "मान 0 के साथ एक अभिन्न निरंतर अभिव्यक्ति" या "मान 0 के साथ एक अभिन्न निरंतर अभिव्यक्ति, void * को डाली जाती void * "। विशेष रूप से, यदि कार्यान्वयन उन विकल्पों के पूर्व का चयन करता है, तो

 int x = __builtin_null; int y = __builtin_null + 1; 

एक मान्य अनुवाद इकाई है, जो क्रमशः 0 और 1 के पूर्णांक मानों को x और y सेट कर रहा है। यदि यह बाद का चयन करता है, तो निश्चित रूप से, दोनों बाध्यता उल्लंघन (क्रमशः 6.5.16.1, 6.5.6 क्रमशः void * , void * 6.2.5p19 प्रति "ऑब्जेक्ट प्रकार के संकेतक" नहीं हैं; 6.7.8 पी 11 इनिशियलाइज़ेशन के लिए असाइनमेंट के लिए बाधाओं को लागू करता है )। और मैं यह नहीं देखता कि कार्यान्वयन ऐसा क्यों करेगी यदि नल का "दुरुपयोग" करने के लिए बेहतर निदान उपलब्ध कराने के लिए नहीं, तो ऐसा लगता है कि यह विकल्प जो अधिक कोड को अमान्य करता है, ले जाएगा।

मान 0 के साथ एक अभिन्न निरंतर अभिव्यक्ति, या इस प्रकार एक अभिव्यक्ति को शून्य * टाइप करने के लिए डाला जाता है, जिसे शून्य सूचक स्थिरांक कहा जाता है

NULL जो एक कार्यान्वयन-परिभाषित नल सूचक निरंतर को बढ़ाता है;

इसलिए या तो

शून्य == 0

या

शून्य == (शून्य *) 0

अशक्त सूचक स्थिरांक 0 का मूल्यांकन करना चाहिए , अन्यथा अभिव्यक्तिएं जैसे !ptr अपेक्षा के अनुरूप काम नहीं करेगा

शून्य मैक्रो एक 0-मूल्य अभिव्यक्ति के लिए फैलता है; AFAIK, यह हमेशा होता है