2013-04-29 13 views
6

अगर मैं सभी निम्नलिखित ठीक है कार्य करें:static_cast शून्य * चार * बनाम static_cast शून्य ** चार **

char* cp = "abc"; 
void* vp = NULL; 
vp = static_cast<void*>(cp);//ok 
cp = static_cast<char*>(vp);//ok 

लेकिन निम्नलिखित नहीं है:

char** cpp = &cp; 
void** vpp = NULL; 
vpp = static_cast<void**>(cpp);//error C2440: 'static_cast': 
           //cannot convert from 'char **' to 'void **' 
cpp = static_cast<char**>(vpp);//error C2440: 'static_cast': 
           //cannot convert from 'void **' to 'char **' 

कृपया किसी को समझा सकता है मैं क्यों दूसरे उदाहरणों की अनुमति नहीं है। कृपया सी ++ मानक को अपने पूरे उत्तर के रूप में उद्धृत न करें, क्योंकि मैंने पहले ही जवाब देखे हैं जो उद्धरण देते हैं, और मुझे समझ में नहीं आता कि उनका क्या अर्थ है। मैं क्यों समझना चाहता हूं दूसरे उदाहरण काम नहीं करते हैं (यानी यदि आप एक उदाहरण दे सकते हैं जहां यह खतरनाक होगा कि यह एक बड़ी मदद होगी)। क्योंकि मुझे यह नहीं मिला है। मेरे लिए, दोनों उदाहरण कास्टिंग पॉइंटर्स हैं। संकेत का एक अतिरिक्त स्तर कोई फर्क क्यों पड़ता है?

+6

आप किसी भी सूचक को 'शून्य * ', और स्थिर दिशा में स्थिर-कास्ट में रूपांतरित कर सकते हैं। लेकिन यह सामान्य रूप से 'टी *' और 'यू *' के लिए सच नहीं है, जो असंबंधित हैं। (अब 'टी = char *' और 'यू = शून्य * ') –

+0

सोचें कि आप' char ** 'को' void *' और इसके विपरीत बना सकते हैं। –

+1

@ केरेक एसबी - हाँ, लेकिन इसकी अनुमति क्यों नहीं है? यह असुरक्षित कब होगा? – e244

उत्तर

12

एक void * सूचक "कुछ भी" पर इंगित कर सकते हैं, और यह एक void * करने के लिए सभी संकेत कन्वर्ट करने के लिए वैध है, और यह कुछ अन्य प्रकार के void * से सभी संकेत कन्वर्ट करने के लिए मान्य है।

हालांकि, एक void ** एक सूचक है कि एक void * मूल्य ओर इशारा करता है। और char ** एक सूचक है जो char * मान को इंगित करता है। ये प्रकार एक दूसरे से परिवर्तनीय प्रकारों को इंगित नहीं करते हैं। यदि आप ऐसा करने की ज़रूरत है, तो आप void **vpp = reinterpret_cast<void **>(cpp); का उपयोग कर सकते हैं, लेकिन यह "सुरक्षित नहीं है" (आप मूल रूप से संकलक को बता रहे हैं "देखो, मुझे पता है कि मैं यहाँ क्या कर रहा हूं, तो बस इसे करें", जो आप नहीं कर सकते वास्तव में अपेक्षित ...)

+0

+1 "सुरक्षित नहीं" के बारे में नोट के लिए +1 –

+0

मुझे खेद है, मुझे अभी भी यह नहीं मिला है। अगर कुछ स्ट्रिंग में पता 0x12345678 है, तो मैं इसे अपने char * या my void * में डाल सकता हूं। अगर मेरे char * का पता 0x87654321 है, तो मैं अपने शून्य ** में वह मान क्यों नहीं डाल सकता (पता 0x87654321)? अर्थात।static_cast 0x12345678 को शून्य * के लिए क्यों ठीक है, लेकिन static_cast 0x87654321 को शून्य के लिए ठीक नहीं है **? कब/क्यों यह असुरक्षित होगा? – e244

+0

@ e244: मुद्दा यह है कि यदि आप उस रूपांतरण की अनुमति देते हैं तो आप आसानी से (और बिना किसी स्पष्ट कलाकार के) टाइप सिस्टम को विचलित कर सकते हैं। मैंने एक उत्तर के रूप में एक लंबा स्पष्टीकरण प्रदान किया है, लेकिन संक्षिप्त वर्णन यह होगा कि डबल पॉइंटर आपको असुरक्षित तरीके से डेटा बदलने की अनुमति देता है। –

6

प्रतिबंध प्रणाली को तोड़ने से बचने के लिए है। पहला रूपांतरण ठीक है:

type *p = ...; 
void *vp = p; 

आप दूर प्रकार दे रहे हैं, आप नहीं बहुत ज्यादा क्षति वास्तविक मान पर बिना के बाद से वहाँ एक void वस्तु के साथ किया जा करने के लिए कम है दण्ड कर सकते हैं और vp में सभी परिवर्तन सूचक के लिए स्थानीय हैं और p को प्रभावित नहीं कर सकते हैं।

तो दूसरे मामले अनुमति दी गई थी:

type **p = ...; 
void **vp = p; 

तो पूरी तरह से देख रही है और सही कोड आपके आवेदन तोड़ सकते थे। उदाहरण के लिए:

int *parray[10]; 
int **p = parray; 
void **vp = p; 
*vp = new double(); // now parray[0] is a pointer to a double object, 
        // not a pointer to an int!!! 

टाइप सिस्टम को हटा दिया गया है।

यही समस्या है कि दूसरे मामले में ऐसे ऑपरेशन हैं जिन्हें गंतव्य पॉइंटर पर लागू किया जा सकता है जो मूल ऑब्जेक्ट को संशोधित कर सकता है और बग का कारण बन सकता है। इसी तरह के उदाहरण const अन्य मामलों के साथ मिल सकते हैं (आप int* से const int* को परिवर्तित कर सकते हैं, लेकिन आप int** से const int** को परिवर्तित नहीं कर सकते हैं ...)।

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