2010-07-21 6 views
10

सी ++ मानक के अनुसार, किसी अन्य प्रकार के पॉइंटर T* के reinterpret_cast किसी अन्य प्रकार के सूचक Q*can change or not change the pointer value कार्यान्वयन के आधार पर।reinterpret_cast का कोई वास्तविक उदाहरण एक सूचक मूल्य बदल रहा है?

मुझे बहुत दिलचस्पी है - क्या सी ++ कार्यान्वयन का कोई वास्तविक उदाहरण है जहां reinterpret_cast के साथ किसी अन्य सूचक प्रकार के सूचक को कास्टिंग सूचक को बदलता है? क्या और क्यों बदल गया है?

+0

आपका मतलब है, "मूल्य बदलता है" सूचक बिंदु? – akira

+0

@किरा: नहीं, सूचक के मूल्य को बदलता है – sharptooth

+0

आपका मतलब है: 'टी * टी = 0x13; क्यू * क्यू = 0x42; टी = reintrepret_cast (क्यू); 'टी '= 0x42' पैदा करता है? – akira

उत्तर

6

ध्यान दें कि जब मानक कहता है कि यह संभवतः कुछ कर सकता है या नहीं कर सकता है, तो इसका मतलब यह नहीं है कि कोई मौजूदा कार्यान्वयन है जिसमें वह व्यवहार है, केवल वे ही कर सकते हैं।

निकटतम जो मैं सोच सकता हूं वह एक वास्तुकला है जहां हार्डवेयर द्वारा टाइप संरेखण की आवश्यकता होती है, और एक कार्यान्वयन जो आवश्यक होने पर संरेखण को सही करने का निर्णय लेता है। की तरह कुछ:

aligned8 var; 
aligned1 *p = reinterpret_cast<aligned1*>(&var); 
aligned1 *q = p + 1; // assuming aligned 1 size is not multiple of 8 
aligned8 *a = reinterpret_cast<aligned8*>(q); // [1] 

एक आवश्यकता है कि a के लिए एक वैध सूचक यह 8 के एक स्मृति स्थिति पता करने के लिए एक से अधिक है होना करने के लिए हो सकती है, जबकि कम संरेखण आवश्यकताओं के साथ तर्क q किसी भी स्मृति पता दर्शाए सकता है।

2
class A1 { int a1; }; 
class A2 { int a2; }; 

class B: public A1, public A2 { }; 

#define DBG(val) cout << #val << ": " << val << endl 

// test code 
B b; 
DBG(&b);           // prints 0x42 

void *p_blank = &b; 
DBG(p_blank);          // prints 0x42 
A2 *p_a2 = &b; 
DBG(p_a2);           // prints 0x46 
void *p_reinterpreted = reinterpret_cast<A2*>(&b); 
DBG(p_reinterpreted);        // prints 0x42 
A2 *p_reinterpreted2 = reinterpret_cast<A2*>(&b); 
DBG(p_reinterpreted2);        // prints 0x42 

A2 *p_a2 = &b साधन मुझे बी वस्तु के भीतर एक ए 2 वस्तु के लिए सूचक दे। reinterpret_cast<A2*>(&b) का अर्थ है मुझे बी को पॉइंटर दें और इसे ए 2 पॉइंटर के रूप में देखें। इस reinterpret_cast के परिणाम में 'पॉइंटर टू ए 2' प्रकार है, इसलिए यह शून्य * चर (या ए 2 * चर) को असाइन किए जाने पर कोई चेतावनी नहीं देता है।

+0

'ए 2 * पी_ए 2 = & बी; 'मुझे आश्चर्य है ... – akira

+5

आपके उदाहरण में' reinterpret_cast' मूल्य को बिल्कुल नहीं बदलता है ... आप बंद हैं मुझे डर है। –

+0

'ए 2 * पी_ए 2 = & बी; 'आप अंतर्निहित रूपांतरण का उपयोग करते हैं जो' static_cast' के बराबर है, 'reinterpret_cast' नहीं। – sharptooth

0

Reinterpret_cast कभी भी एक अलग पता नहीं लौटाएगा - सटीक पते की प्रतिलिपि बनाना आवश्यक है।

डेविड रोड्रिगेज जैसे कई विरासतों के मामलों में, आधारों में से एक का पता लेना उस पते को वापस कर सकता है जिसने पहले आधार के पते पर ऑफसेट किया है। Reinterpret_cast उस ऑफसेट पते को वापस कर देगा, लेकिन यदि आप इसे अपस्टास्ट पते के रूप में देखते हैं, तो नरक आ जाएगा।

उपेक्षा के लिए, static_cast किसी दिए गए से अलग पता वापस कर सकता है। यदि आपके पास पता है तो आधारों में से एक है, और वह पता पहले आधार पते पर ऑफसेट पर है, static_cast अपस्टेड ऑब्जेक्ट के लिए एक मान्य पता लौटाएगा, जो पहले आधार के पते के बराबर है और इस प्रकार बराबर नहीं है सूचक पास करने के लिए।

इसे छोटा करने के लिए: reinterpret_cast आपको हमेशा एक ही पता देता है। Static_cast और dynamic_cast एक अलग पता लौटा सकता है, उदा। कई मामलों में कई विरासत शामिल हैं।

static_cast और dynamic_cast के बीच का अंतर यह है कि static_cast यह जांच नहीं करता है कि आप जो पॉइंटर देते हैं वह कास्ट के लिए सही वस्तु है, इसलिए इसे कॉल करने से पहले सुनिश्चित करें।

+1

"आवश्यक" से जुड़े एक बयान को स्रोत के साथ बैक अप लेना चाहिए। मैं देखता हूं कि आपको कम सख्ती से गठबंधन प्रकार के सूचक के रूप में परिवर्तित करने की अनुमति है * और फिर वापस *, और "किसी भी अन्य सूचक रूपांतरण का नतीजा निर्दिष्ट नहीं है।" (5.2.10/7) – Potatoswatter

+1

उम, मैंने संरेखण के मुद्दों को पूरी तरह याद किया, मैं देख सकता हूं कि यह पता कैसे बदल जाएगा। सुधारों के लिए धन्यवाद। – Alex

1

परेशानी का सबसे अधिक संभावित स्रोत वेक्टर मशीन पर है जहां स्केलर ऑपरेशंस वैक्टर के संदर्भ में परिभाषित किया जाता है, और स्केलर पॉइंटर में वेक्टर में इंडेक्स के साथ वेक्टर के सूचक होते हैं। ऐतिहासिक रूप से मूल क्रे वास्तुकला इस तरह था और इससे सिरदर्द हो गया। आजकल आप जीपीयू पर ऐसा कुछ देख सकते हैं, लेकिन मैं अपने सिर के ऊपर से कुछ विशिष्ट नहीं बता सकता।

सबसे संभावित प्रभाव छिड़काव है क्योंकि गंतव्य सूचक प्रकार सूचकांक भाग निर्दिष्ट करने के लिए बिट्स की कमी है।सी ++ 11 इस दिशा में किसी भी पॉइंटर प्रकार को reinterpret_cast एड होने की इजाजत देता है जब तक कि उनके पास समान संरेखण आवश्यकताएं हों। कड़े संरेखण द्वारा "शून्य" बिट्स मौजूद नहीं हैं।

एक वस्तु सूचक स्पष्ट एक अलग प्रकार का एक उद्देश्य सूचक के लिए परिवर्तित किया जा सकता है। जब "पॉइंटर टू टी 1" का एक प्रावधान v "पॉइंटर से सीवी टी 2" प्रकार में परिवर्तित होता है, तो परिणाम static_cast<cv T2*>(static_cast<cv void*>(v)) होता है यदि टी 1 और टी 2 मानक-लेआउट प्रकार (3.9) और टी 2 की संरेखण आवश्यकताओं हैं की तुलना में कोई कठोर टी 1, या यदि कोई भी प्रकार शून्य है। टाइप "पॉइंटर टू टी 2" के प्रकार के रूप में "पॉइंटर टू टी 2" (जहां टी 1 और टी 2 ऑब्जेक्ट प्रकार हैं और जहां टी 2 की संरेखण आवश्यकताएं टी 1 की तुलना में कठोर नहीं हैं) और उसके मूल प्रकार पर वापस मूल सूचक मूल्य उत्पन्न करता है। ऐसे किसी अन्य सूचक का परिणाम रूपांतरण अनिर्दिष्ट है।

1

मुझे नहीं लगता कि प्रश्न सी ++ बनाम सी पॉइंटर कास्ट के लिए अर्थपूर्ण रूप से अलग है। this answer से मैं उदाहरण के लिए केवल एक ही बोली:

डाटा जनरल से

The Eclipse एमवी श्रृंखला है तीन वास्तुकला समर्थित सूचक प्रारूपों (शब्द, बाइट, और बिट संकेत), जिनमें से दो सी compilers द्वारा किया जाता है: बाइट संकेत char* और void*, और

सब कुछ है कि एक reinterpret_cast<Word_Aligned_Type*>(char*) पता चलता है अपनी भावना जिनमें से चरित्र/शब्द में बाइट में बताया जा रहा था खो सकता है, कार्यवाही पूर्ववत करने के लिए शब्द संकेत के लिए।

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