में प्रयोग किया जाता है प्रकार कौन इस तरह के कलाकारों के लिए अनुमति दी है (उदाहरण के लिए यदि T1
एक पॉड प्रकार है और T2
unsigned char
है), static_cast
साथ दृष्टिकोण है मानक द्वारा अच्छी तरह परिभाषित।
दूसरी तरफ, reinterpret_cast
पूरी तरह से कार्यान्वयन-परिभाषित है - केवल एक ही गारंटी है कि आप इसके लिए प्राप्त करते हैं कि आप किसी अन्य सूचक प्रकार के लिए पॉइंटर प्रकार डालें और फिर वापस जाएं, और आपको मूल मान मिलेगा; और, आप एक पॉइंटर प्रकार को एक अभिन्न प्रकार में डाल सकते हैं जो कि पॉइंटर वैल्यू (जो कार्यान्वयन के आधार पर भिन्न होता है, और बिल्कुल मौजूद नहीं है) को पकड़ने के लिए पर्याप्त होता है, और उसके बाद इसे वापस लाया जाता है, और आपको मूल मान मिल जाएगा।
अधिक विशिष्ट होना करने के लिए, मैं सिर्फ मानक के प्रासंगिक भागों बोली होगा, महत्वपूर्ण भागों पर प्रकाश डाला:
5.2.10 [expr.reinterpret.cast]:
मानचित्रण द्वारा किया reinterpret_cast कार्यान्वयन-परिभाषित है। [नोट: यह मूल मान से अलग प्रतिनिधित्व प्रस्तुत कर सकता है, या नहीं हो सकता है।] ... किसी ऑब्जेक्ट के लिए पॉइंटर को अलग-अलग प्रकार के ऑब्जेक्ट में पॉइंटर में स्पष्ट रूप से परिवर्तित किया जा सकता है।) सिवाय इसके कि किसी प्रकार के रावल्यू को परिवर्तित करना "टी 1 के लिए पॉइंटर" प्रकार "पॉइंटर टू टी 2" (जहां टी 1 और टी 2 ऑब्जेक्ट प्रकार हैं और जहां टी 2 की संरेखण आवश्यकताएं टी 1 की तुलना में कोई कठोर नहीं हैं) और इसके मूल प्रकार पर मूल पॉइंटर मान, उत्पन्न होता है ऐसे सूचक रूपांतरण का नतीजा निर्दिष्ट नहीं है।
तो कुछ इस तरह:
struct pod_t { int x; };
pod_t pod;
char* p = reinterpret_cast<char*>(&pod);
memset(p, 0, sizeof pod);
प्रभावी रूप से अनिर्दिष्ट है।
समझाते हुए क्यों static_cast
काम थोड़ा और मुश्किल है। यहाँ ऊपर कोड static_cast
जो मेरा मानना है कि हमेशा की तरह स्टैंडर्ड द्वारा इच्छित कार्य करने की गारंटी है उपयोग करने के लिए फिर से लिखा है: एक बार फिर
struct pod_t { int x; };
pod_t pod;
char* p = static_cast<char*>(static_cast<void*>(&pod));
memset(p, 0, sizeof pod);
, मुझे यह निष्कर्ष निकला कि ऊपर स्टैंडर्ड के वर्गों है कि, एक साथ, मुझे नेतृत्व बोली जाने पोर्टेबल होना चाहिए:
3.9 [मूलभूत।प्रकार]:
पॉड प्रकार टी के किसी भी वस्तु (एक आधार स्तरीय subobject के अलावा अन्य) के लिए, या नहीं, ऑब्जेक्ट प्रकार टी की कोई मान्य मान रखती है, अंतर्निहित बाइट्स (1.7) वस्तु बनाने कर सकते हैं चार या हस्ताक्षरित चार की सरणी में कॉपी किया जाना चाहिए। यदि चार या हस्ताक्षरित चार की सरणी की सामग्री ऑब्जेक्ट में वापस कॉपी की जाती है, तो ऑब्जेक्ट इसके बाद उसका मूल मान रखेगा।
टाइप टी के किसी ऑब्जेक्ट का ऑब्जेक्ट प्रस्तुति एन टी हस्ताक्षर किए गए चार ऑब्जेक्ट्स के प्रकार टी द्वारा ऑब्जेक्ट किया गया है, जहां एन आकार (टी) के बराबर है।
3.9.2 [basic.compound]:
सीवी-योग्य (3.9.3) या सीवी-अयोग्य प्रकार void*
(शून्य करने के लिए सूचक) की वस्तुओं, वस्तुओं को इंगित करने के लिए इस्तेमाल किया जा सकता है अज्ञात प्रकार का। एक void*
कोई ऑब्जेक्ट पॉइंटर पकड़ने में सक्षम होगा। एक सीवी-योग्य या सीवी-अयोग्य (3.9.3) void*
में सीवी-योग्यता या सीवी-अयोग्य char*
के समान प्रतिनिधित्व और संरेखण आवश्यकताएं होंगी।
3,10 [basic.lval]:
एक कार्यक्रम निम्नलिखित प्रकारों में से एक के अलावा अन्य के lvalue के माध्यम से एक वस्तु की संग्रहीत मूल्य तक पहुँचने के लिए प्रयास करता है व्यवहार अपरिभाषित है):
- ...
- एक चार या अहस्ताक्षरित चार प्रकार।
4,10 [conv.ptr]:
प्रकार की जहां टी एक वस्तु प्रकार, "करने के लिए प्रकार का एक rvalue में बदला जा सकता सूचक है" सीवी टी, सूचक "एक rvalue सीवी शून्य। "एक" पॉइंटर से सीवी टी "को" पॉइंटर से सीवी शून्य "में परिवर्तित करने का नतीजा भंडारण स्थान की शुरुआत के लिए इंगित करता है जहां टाइप टी का ऑब्जेक्ट रहता है, जैसे कि ऑब्जेक्ट सबसे व्युत्पन्न वस्तु है (1.8) प्रकार टी (यानी, बेस क्लास सबोबजेक्ट नहीं है)।
5.2.9 [expr.static.cast]:
किसी भी मानक रूपांतरण अनुक्रम (खंड 4), lvalue करने वाली rvalue (4.1), सरणी-topointer के अलावा अन्य का प्रतिलोम (4.2), फ़ंक्शन-टू-पॉइंटर (4.3), और बूलियन (4.12) रूपांतरण, static_cast का उपयोग करके स्पष्ट रूप से निष्पादित किया जा सकता है।
[संपादित करें] दूसरी ओर, हम इस मणि है:
9.2 [class.mem]/17:
एक पॉड-struct वस्तु के लिए एक सूचक, उपयुक्त रूप से reinterpret_cast का उपयोग करके परिवर्तित किया गया है, इसके प्रारंभिक सदस्य को इंगित करता है (या यदि वह सदस्य थोड़ा-फ़ील्ड है, फिर उस यूनिट में जिसमें वह रहता है) और इसके विपरीत।[नोट: हो सकता है इसलिए एक पीओडी-स्ट्रक्चर ऑब्जेक्ट के भीतर अज्ञात पैडिंग हो, लेकिन इसकी शुरुआत में उचित संरेखण प्राप्त करने के लिए आवश्यक नहीं है। ]
जो इंगित करता है कि reinterpret_cast
पॉइंटर्स के बीच किसी भी तरह से "एक ही पता" का तात्पर्य है। जाओ पता लगाओ।
यह पूछने के लिए धन्यवाद। ऐसा लगता है कि जवाब मानक में गहरा हो गया है। (इसे कई बार यूजनेट में पूछा, कोई भी इस बात की गारंटी नहीं दे सकता कि उस स्थिर-कास्ट अनुक्रम बेहतर क्या करता है)। वहां * कुछ * होना है: सी ++ 0x ने 'reinterpret_cast' के spec में कुछ शब्द जोड़ा, जो कि' static_cast' अनुक्रम 'के कुछ प्रकारों के साथ उपयोग किए जाने पर इसे फिर से लिखता है। –
@sinec मुझे पूछना है कि आपको ऐसे कलाकारों को करने के लिए क्यों जरूरी लगता है? मैंने ऐसा करने की आवश्यकता के बिना सालों में सी ++ कोड के शेल्फ लोड लिखे हैं। –
@ नील बटरवर्थ मैंने एक परियोजना पर काम किया (यह मौजूदा कोड में नई विशेषताएं जोड़ने जैसा था) और वहां बहुत सारे पागल जानवर थे, लेकिन यह अनिवार्य था क्योंकि हम विरासत कोड नहीं बदल सके। वैसे भी, मैंने इस सवाल से पूछा क्योंकि मैं एक पुस्तक पढ़ रहा हूं और मुझे इसके लिए कोई स्पष्टीकरण नहीं मिला। – sinek