2009-08-20 17 views
6

के साथ काम नहीं कर रहा है, मैं एक शून्य * चर में एक फ़ंक्शन पॉइंटर डालने की पुनरावृत्ति करना चाहता हूं। फ़ंक्शन पॉइंटर का प्रकार Class* (*)(void*) प्रकार का होगा।vin to reodeterpret_cast * फ़ंक्शन पॉइंटर्स

नीचे नमूना कोड,

class Test 
{ 
    int a; 
}; 

int main() 
{ 
    Test* *p(void **a); 
    void *f=reinterpret_cast<void*>(p);  
} 

ऊपर कोड दृश्य स्टूडियो/86 compilers के साथ अच्छी तरह से काम करता है। लेकिन एआरएम कंपाइलर के साथ, यह संकलन त्रुटि देता है। पता नहीं क्यों।

Error: #694: reinterpret_cast cannot cast away const or other type qualifiers

मैं में Casting a function pointer to another type

मैं नीचे विवरण के बारे में चिंतित था विवरण पढ़ें।

Casting between function pointers and regular pointers (e.g. casting a void (*)(void) to a void*). Function pointers aren't necessarily the same size as regular pointers, since on some architectures they might contain extra contextual information. This will probably work ok on x86, but remember that it's undefined behavior.

कैसे प्रभावी ढंग से void (*)(void*) -> void* से इस तरह के रूपांतरण करने के लिए इतना है कि कम से कम यह compilers के अधिकांश में लगभग एक ही संकलित?

+0

आपको कम से कम एक जोर देना चाहिए कि 'आकार (शून्य *)> = आकार (टेस्ट ** (*) (शून्य **)) '। यदि यह जोर विफल रहता है, तो स्पष्ट रूप से फ़ंक्शन पॉइंटर को 'शून्य *' में संग्रहीत करने का कोई तरीका नहीं है। अगर जोर विफल नहीं होता है, तो यह अभी भी कुछ भी गारंटी नहीं देता है, लेकिन कम से कम यह संभव है कि कलाकार काम कर सके। –

+0

ध्यान दें कि पी वास्तव में टाइप टेस्ट ** (शून्य **) है, और एक फ़ंक्शन है, फ़ंक्शन पॉइंटर नहीं। "टेस्ट * *' "में एक जगह डालने से पार्सिंग प्रभावित नहीं होती है। – MSalters

उत्तर

7

reinterpret_castvoid* पर फ़ंक्शन करने के लिए पॉइंटर डालने के लिए उपयोग नहीं किया जा सकता है। हालांकि कुछ अतिरिक्त चीजें हैं जो सी कास्ट कर सकती हैं जिन्हें स्थैतिक, पुन: व्याख्या और कॉन्स्ट का संयोजन करके अनुमति नहीं दी जाती है, यह रूपांतरण उनमें से एक नहीं है।

सी में कलाकारों की अनुमति है, लेकिन इसका व्यवहार परिभाषित नहीं किया गया है (यानी गोल यात्रा भी काम करने की गारंटी नहीं है)।

कुछ POSIX कार्यों को रूपांतरण को अच्छी तरह से उपयोगी होने की आवश्यकता है।

मैं कई compilers के साथ खेला है मैं यहाँ है:

  • कोई भी उच्चतम अनुरूपता मोड में, सी कलाकारों को रोकने के। कुछ चेतावनी और अनुरूपता स्तर के आधार पर चेतावनी देते हैं, अन्य ने जो कुछ भी मैंने कोशिश की, उसे कोई चेतावनी नहीं दी।
  • reinterpret_cast कुछ कंपाइलरों के साथ भी अधिक आराम से स्तर में एक त्रुटि थी, जबकि अन्य ने बिना किसी चेतावनी के सभी मामलों में इसे स्वीकार कर लिया था।

सी ++ 0 एक्स के लिए अंतिम उपलब्ध ड्राफ्ट में, फंक्शन पॉइंटर्स और ऑब्जेक्ट पॉइंटर्स के बीच reinterpret_cast सशर्त रूप से समर्थित है।

ध्यान दें कि यदि यह समझ में आता है या नहीं, तो संकलक से अधिक लक्ष्य पर निर्भर करेगा: जीसीसी जैसे पोर्टेबल कंपाइलर के पास लक्ष्य आर्किटेक्चर और संभवतः एबीआई द्वारा लगाए गए व्यवहार होंगे।

अन्य के रूप में, टिप्पणी करना है

Test* *p(void **a); 

एक समारोह, नहीं कार्य करने के लिए एक सूचक परिभाषित करता है। लेकिन अंतर्निहित रूपांतरण करने के लिए सूचक को फ़ंक्शन reinterpret_cast के तर्क के लिए बनाया गया है, तो reinterpret_cast प्राप्त करने के लिए Test** (*p)(void** a) क्या है।

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

+0

सी कास्ट पूरी तरह से काम किया। धन्यवाद। :) – vprajan

+0

(लगभग -1) मुझे नहीं लगता कि यह सही है, क्या आप इसके लिए एक संदर्भ प्रदान कर सकते हैं? यह मेरी समझ है कि सी-स्टाइल कास्ट नई कास्ट शैलियों के संदर्भ में परिभाषित किया गया है। इसलिए, यदि reinterpret_cast का उपयोग करके ऐसा करना संभव नहीं है तो सी-स्टाइल कास्ट के साथ यह संभव नहीं है। –

0

Test* *p(void **a);Test* (*p)(void **a) नहीं होना चाहिए?

शायद यह आपकी समस्या है?

+0

टेस्ट * * पी (शून्य ** ए) टेस्ट * (*) (शून्य **) टाइप करने का भी हल कर रहा है .. इसलिए मुझे लगता है कि दोनों प्रतिनिधित्व वैध हैं। क्योंकि मुझे लगता है कि जिस तरह से भी करने की कोशिश की इस बात का यकीन है .. – vprajan

3

तुम सिर्फ एक सूची में समारोह सूचक के विभिन्न प्रकार के स्टोर करने के लिए देख रहे हैं तो आप एक आम समारोह सूचक प्रकार पर कास्ट कर सकते:

class Test { 
    int a; 
}; 

int main() 
{ 
    Test* *p(void **a); 
    void (*f)()=reinterpret_cast<void (*)()>(p); 
} 

यह reinterpret_cast के माध्यम से करने के लिए मान्य है (5.2.10/6):

A pointer to a function can be explicitly converted to a pointer to a function of a different type. The effect of calling a function through a pointer to a function type (8.3.5) that is not the same as the type used in the definition of the function is undefined. Except that converting an rvalue of type "pointer to T1" to the type "pointer to T2" (where T1 and T2 are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified.

7

reinterpret_cast केवल करने के लिए

  • ऐड constness
  • 01 इस्तेमाल किया जा सकता
  • एक अभिन्न प्रकार काफी बड़ी इसे पकड़ और वापस
  • अलग प्रकार
  • के एक समारोह के लिए एक सूचक को एक समारोह के लिए एक सूचक परिवर्तित का एक उद्देश्य के लिए सूचक को एक वस्तु के लिए सूचक कन्वर्ट करने के लिए एक सूचक परिवर्तित विभिन्न प्रकार
  • अलग प्रकार
  • के एक सदस्य के कार्य करने के लिए एक सूचक को एक सदस्य के कार्य करने के लिए एक सूचक परिवर्तित विभिन्न प्रकार के एक सदस्य वस्तु के लिए एक सूचक को एक सदस्य वस्तु के लिए एक सूचक परिवर्तित
  • और reinterpret_cast<T&>(x) के बराबर है *reinterpret_cast<T*>(&x) (बिल्टिन & का उपयोग करके और *) जब भी उपरोक्त नियमों का उपयोग कर दूसरी कास्ट संभव हो।

(मानक की धारा 5.2.10 देखें)

यह विशेष रूप से इसका मतलब है कि एक सूचक से एक डाली void * को कार्य करने के लिए संभव नहीं है, लेकिन आप इसे void(*)() पर कास्ट कर सकते।


संपादित करें (2017): जवाब ऊपर केवल के लिए सी ++ 03 सही है। सी ++ 11 से सी ++ 17 में, यह क्रियान्वयन परिभाषित किया गया है यदि फ़ंक्शन पॉइंटर्स और void * के बीच रूपांतरण की अनुमति है। यह आमतौर पर POSIX संगत सिस्टम पर मामला है क्योंकि dlsym() को void * वापस करने के लिए घोषित किया गया है, और ग्राहकों को reinterpret_cast यह सही फ़ंक्शन पॉइंटर प्रकार पर होने की उम्मीद है।

रूपांतरणों की पूरी सूची के लिए cppreference.com देखें।

2

अन्य (। - लेकिन चुपचाप compilers द्वारा सहन static_cast यहां इस्तेमाल किया जा करने का इरादा है दृढ़ता से, बोलने का उपयोग कर reinterpret_cast भी अनुमति नहीं है void* कुछ भी करने के लिए कास्टिंग) बाहर आपको लगता है कि कलाकारों के लिए नहीं कर सकते इशारा किया।

मैं आमतौर पर निम्न कार्य है, जो एक प्रकार यमक कर रहा है, और यह करने के लिए सिफारिश की रास्ता है, (dlopen की मैनपेज बातचीत करने के बारे में है जिसके अनुसार - एक समारोह कोvoid*से कास्टिंग सूचक)। फ़ंक्शन पॉइंटर का पता लेना आपको डेटा-पॉइंटर देगा: फ़ंक्शन पॉइंटर को पॉइंटर। यह आपको इसे void* पर डालने की अनुमति देगा। यह दिखाता है कि यह void* (फ़ंक्शन पॉइंटर के बजाए) पर इंगित कर रहा है, और उसके बाद इसे पढ़ता है।

Test* (*pF)(void **a); 
void *p = *(void**)(void*)&pF; 

void* को मध्यस्थ डाली वह आंतरिक रूप से दो static_cast के उपयोग करने पर बनाता है, और जीसीसी एक प्रकार यमक के बारे में चेतावनी के बारे में चुप रहे बनाता है। सी ++ का उपयोग करते हुए शैली डाले, इस का एक संयोजन की तरह लग रहा दो static_cast के

void *p = *static_cast<void**>(static_cast<void*>(&pF)); 

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


आप एक समारोह है, और इसे करने के लिए एक void* इशारा चाहते हैं, आप यह सब एक पंक्ति में कर सकते हैं, लेकिन यह वाक्य रचना पर थोड़ा बोझिल है। यहाँ यह यह कैसे किया जा सकता है, लेकिन मैं इसकी सलाह नहीं देते अगर आप समस्या है इसे पढ़ने के लिए है - आप फिर भी अंदर एक मैक्रो

// using the function declaration you provided 
Test** pF(void **a); 
void *p = *(void**)(void *) &(Test** (* const&)(void **a))&pF; 

चाल इसका इस्तेमाल कर सकते प्रकार ऐसा करने में सक्षम किया जा रहा शुरू करने के लिए, लेकिन अस्थायी फ़ंक्शन पॉइंटर को कॉन्स्ट के संदर्भ में बदलने के लिए है, जिसे आप पता ले सकते हैं, और उसके बाद ऊपर की तरह आगे बढ़ सकते हैं।

स्पष्ट सी ++ शैली static_cast का उपयोग करते हुए, यह अधिक जटिल लग रहा है, क्योंकि आपको दृढ़ता को ध्यान में रखना है। सी शैली कास्ट स्वचालित रूप से उस के साथ सौदा किया। मज़े करो!

int main() { 
    Test** pF(void **a); 
    void *p = *static_cast<void* const*>(
     static_cast<void const*>(
     &static_cast<Test** (* const&)(void **a)>(&pF))); 
} 
+0

इस के लिए धन्यवाद - कोड मेरी आंखों क्रॉल करता है, लेकिन यह ठीक से काम करते हैं और यहां तक ​​कि जीसीसी और बजना में चेतावनी स्तर से बाहर maxed के साथ चेतावनी/त्रुटियों से बचने के लिए लगता है। – snogglethorpe

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