2010-08-12 17 views
6

मैं एक कॉलबैक समारोह के लिए कोड लिखने की जरूरत है (यह ATL के भीतर से बुलाया जाएगा, लेकिन जो वास्तव में महत्वपूर्ण नहीं है):क्या static_cast एक नल पॉइंटर को एक नल पॉइंटर में बदल सकता है?

HRESULT callback(void* myObjectVoid) 
{ 
    if(myObjectVoid == 0) { 
     return E_POINTER; 
    } 
    CMyClass* myObject = static_cast<CMyClass*>(myObjectVoid); 
    return myObject->CallMethod(); 
} 
यहाँ

void*CMyClass के लिए सूचक होने की गारंटी है, इसलिए static_cast कानूनी है । मेरी चिंता यह है कि कोड पोर्टेबल (कम से कम दृश्य C++ के नए संस्करणों के लिए) जितना संभव हो सके होना चाहिए। तो सुपर-पैरानोइक होने के लिए मैं CMyClass* पॉइंटर को भी जांचने के इच्छुक हूं - मेरा मतलब है कि अगर यह शून्य हो जाता है तो क्या होगा?

if(myObjectVoid == 0) { 
     return E_POINTER; 
    } 
    CMyClass* myObject = static_cast<CMyClass*>(myObjectVoid); 
    if(myObject == 0) { 
     return E_POINTER; 
    } 

दूसरा चेक उचित है? क्या गैर-शून्य पॉइंटर को शून्य सूचक में बदलने के लिए static_cast के लिए यह संभव है?

+3

क्यों न सिर्फ बिना शर्त डाली, और कलाकारों के बाद अशक्त के लिए जाँच? static_cast सूचक को कम करने के लिए नहीं जा रहा है। –

+0

@ लोगन कैपल्दो: जितनी जल्दी हो सके जांचना बेहतर लगता है। – sharptooth

उत्तर

7

static_cast सूचक मूल्य बदल सकते हैं, अगर आप विभिन्न ऑफसेट पर वस्तु भागों के बीच डाली:

class A{ int x; }; class B{ int y; }; 
class C : A,B {}; 

C *c=new C(); 

B *b=c; 
// The B part comes after the A part in C. Pointer adjusted 

C *c2=static_cast<C*>(b); 
// Pointer gets adjusted back, points to the beginning of the C part 

हालांकि, "नल पॉइंटर मूल्य (4.10) गंतव्य प्रकार के नल पॉइंटर मूल्य में बदल जाती है । " (5.2.9-8), अर्थात अगरcNULL है, तो b भी NULL है (और नहीं समायोजित) और इस तरह c2NULL को तैयार है। पूरी बात का अर्थ है: यदि स्थैतिक कास्टिंग गैर-न्यूल myObjectVoidNULL उत्पन्न करता है, तो myObjectVoid का मान किसी भी तरह से सिस्टम सिस्टम को बाधित करके प्राप्त किया गया था। और इसका मतलब है कि संकलक आपकी दूसरी जांच को फेंक सकता है क्योंकि "यह वैसे भी नहीं हो सकता है"।

0

एकमात्र परिवर्तन static_cast शब्द-संरेखण के लिए एक पॉइंटर को बनाना चाहिए। तो, सिद्धांत रूप में, myObjectVoid की स्मृति में अंतिम बाइट की ओर इशारा किया गया है, यह संभव है कि इसे 0 पर 'गठबंधन' किया जा सके, लेकिन मुझे यह यथार्थवादी चिंता के रूप में नहीं दिखाई देता है।

+0

यदि यह संभव था, तो क्या यह एक बड़ी समस्या नहीं होगी? मैंने हमेशा सोचा कि 0 एकमात्र मूल्य था जो वैध सूचक नहीं हो सका। – ereOn

+0

असली सवाल यह है कि पता ऊपर या नीचे गोलाकार किया जाएगा या यह कार्यान्वयन परिभाषित किया गया है? –

5

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

वस्तु संकेत और शून्य संकेत के बीच परिवर्तित करने की विशिष्ट स्थिति में, मानक यह कहना (5.2.9/10) है:

"पॉइंटर टू ऑब्जेक्ट" प्रकार का मान "पॉइंटर से void" में परिवर्तित किया गया है और मूल सूचक प्रकार पर वापस मूल मूल्य होगा।

और इस (4,10/3)

एक "सूचक टी करने के लिए" भंडारण स्थान के शुरू करने के अंक "void सूचक" एक को बदलने का परिणाम जहां प्रकार की वस्तु टी रहता है

तो मूल और अंतिम वस्तु संकेत दिए गए एक ही हो जाएगा, और void सूचक अशक्त यदि और केवल यदि वस्तु संकेत दिए गए हैं हो जाएगा।

0

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

+1

वैसे आप वहां जाते हैं। गैर-वास्तविक दुनिया स्थितियों में, static_cast करने के लिए एक सावधानी से गढ़ी गई सूचक में गुजर कारण बन सकता है यह द्वारा समायोजित किया जा करने के लिए एक ऑफसेट यह NULL बनाता है। बेशक, यह वास्तविक जीवन में कभी नहीं होने वाला है। –

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