2011-12-22 8 views
5

मैं जहाँ मैं '\ 0' के साथ सूचक तुलना में मेरे कोड में एक बग मिला।' 0' वाले पॉइंटर की तुलना करना ठीक क्यों है? (लेकिन 'ए')

आश्चर्य है कि संकलक ने मुझे इस बग के बारे में चेतावनी क्यों नहीं दी मैंने निम्नलिखित कोशिश की।

#include <cassert> 

struct Foo 
{ 
    char bar[5]; 
}; 

int main() 
{ 
    Foo f; 
    Foo* p = &f; 
    p->bar[0] = '\0'; 
    assert(p->bar == '\0'); // #1. I forgot [] Now, comparing pointer with NULL and fails. 
    assert(p->bar == 'A');  // #2. error: ISO C++ forbids comparison between pointer and integer 
    assert(p->bar[0] == '\0'); // #3. What I intended, PASSES 
    return 0; 
} 

'0' के बारे में विशेष क्या है जो # 1 कानूनी और # 2 अवैध बनाता है?

अपने जवाब के लिए एक संदर्भ या उद्धरण जोड़ें।

उत्तर

8

क्या यह कानूनी और अच्छी तरह से परिभाषित करता है तथ्य यह है '\0' है कि एक नल पॉइंटर निरंतर इसलिए यह एक नल पॉइंटर मूल्य बनाने के लिए किसी भी सूचक प्रकार में बदला जा सकता।

आईएसओ/आईईसी 14882: 2011 4.10 [conv.ptr]/1:

एक नल पॉइंटर निरंतर कि शून्य करने के लिए मूल्यांकन करता है पूर्णांक प्रकार का एक अभिन्न निरंतर अभिव्यक्ति prvalue या प्रकार std::nullptr_t के prvalue है । एक शून्य सूचक स्थिर को एक सूचक प्रकार में परिवर्तित किया जा सकता है; नतीजा उस प्रकार के शून्य सूचक मूल्य है और ऑब्जेक्ट पॉइंटर या फ़ंक्शन पॉइंटर प्रकार के हर दूसरे मूल्य से अलग है। इस तरह के एक रूपांतरण एक नल पॉइंटर रूपांतरण कहा जाता है।

'\0' की वजह से char एक पूर्णांक प्रकार है और \0 मान शून्य है "पूर्णांक प्रकार है कि शून्य करने के लिए मूल्यांकन करता है के अभिन्न निरंतर अभिव्यक्ति prvalue" आवश्यकताओं को पूरा करती।

अन्य पूर्णांक को केवल reinterpret_cast के माध्यम से एक सूचक प्रकार में स्पष्ट रूप से परिवर्तित किया जा सकता है और परिणाम केवल सार्थक है यदि पूर्णांक एक वैध सूचक को पर्याप्त आकार के पूर्णांक प्रकार में परिवर्तित करने का परिणाम था।

5

'\0'0 लिखने का एक अलग तरीका है। मैं, लगता है कि यह कानूनी की तुलना संकेत है 0 समझ में आता है करने के लिए कोई फर्क नहीं पड़ता कि कैसे आप 0 लिखा था, जबकि वहाँ किसी भी अन्य गैर-सूचक प्रकार के लिए सूचक की तुलना करने के लिए किसी भी मान्य अर्थ है लगभग कभी नहीं।

+1

और 0 को 'nullptr' में परिवर्तित किया गया है (सी ++ 11 parlance में) –

+1

@ बेसिलस्टारनकेविच, मुझे नहीं लगता कि यह इस मामले में है। शून्य सूचक स्थिरांक सीधे उचित प्रकार के शून्य सूचक मूल्य में परिवर्तित हो जाता है। – avakar

+0

लेकिन 'nullptr' उचित प्रकार के शून्य सूचक मूल्य को इंगित करता है ... –

1

यह सी ++ की एक डिजाइन त्रुटि है। नियम कहता है कि मूल्य शून्य के साथ किसी भी पूर्णांक निरंतर अभिव्यक्ति को शून्य सूचक स्थिर के रूप में माना जा सकता है।

यह मूर्खतापूर्ण अत्यधिक संदिग्ध निर्णय के रूप में नल पॉइंटर '\0' (के रूप में आप पाया जाता है) लेकिन (1==2) या यहाँ तक कि यह भी चीजों की तरह !!!!!!!!!!!1 (एक से मिलता-जुलता उदाहरण है कि पर 'सी ++ प्रोग्रामिंग भाषा ", पता नहीं मौजूद है का उपयोग करने के लिए अनुमति देता है अगर स्ट्रॉस्ट्रप सोचता है कि यह वास्तव में एक "शांत" सुविधा है)।

इस अस्पष्टता IMO भी जब त्रिगुट ऑपरेटर अर्थ और अंतर्निहित रूपांतरण नियमों के साथ मिश्रित वाक्य रचना परिभाषा का तरीका बता बनाता है: मैं एक मामला है जिसमें तीन compilers एक संकलन नहीं किया गया था और अन्य दो में से अलग अलग अर्थ के साथ संकलन कर रहे थे खोजने याद ... और मानक पढ़ने और सीसीएलसी ++ पर विशेषज्ञों से पूछने पर एक दिन बर्बाद करने के बाद। मैं यह तय करने में सक्षम नहीं था कि तीनों में से कौन सा कंपाइलर सही था।

+0

क्या यह सी में एक डिजाइन त्रुटि नहीं होगी, इस बात पर विचार करते हुए कि यह सुविधा विरासत में मिली है? (यह नहीं कि मैं उन निर्णयों की मूर्खता के बारे में आपसे सहमत हूं) – avakar

+0

@avakar: मुझे ऐसा नहीं लगता है। असल पॉइंटर के लिए असल में सी और सी ++ नियम भिन्न होते हैं और सी ++ के लिए रूपांतरण नियम भी अधिक जटिल होते हैं, इसलिए वास्तविक "पिछड़ा संगतता" मौजूद नहीं है। उदाहरण के लिए काफी सामान्य '# परिभाषित न्यूल ((शून्य *) 0)' सी (हैड) सी सिस्टम हेडर में उपयोग किया गया है सी ++ के लिए मान्य 'पूर्ण' परिभाषा नहीं है। – 6502

+0

यह महत्वपूर्ण नहीं है, लेकिन आपको क्या याद आया? –

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