2012-01-23 15 views
6

अगर मैं निम्नलिखित struct है:तत्व के साथ संगत एक तत्व की एक संरचना है?

struct Foo { int a; }; 

सी ++ मानक के अनुरूप bellow कोड है? मेरा मतलब है, क्या यह एक "अपरिभाषित व्यवहार" उत्पन्न नहीं कर सकता है?

Foo foo; 
int ifoo; 

foo = *reinterpret_cast<Foo*>(&ifoo); 

void bar(int value); 

bar(*reinterpret_cast<int*>(&foo)); 

auto fptr = static_cast<void(*)(...)>(&bar); 
fptr(foo); 
+1

मुझे पूरा यकीन है कि संरचना में int की तुलना में अधिक कठोर संरेखण आवश्यकताएं हो सकती हैं, इसलिए जब आप 'int' से' Foo' में पुन: व्याख्या करते हैं तो आप यूबी में भाग लेते हैं। मैं दूसरे तरीके के बारे में निश्चित नहीं हूँ। – avakar

उत्तर

10

9,2/20 N3290 में कहते हैं

एक मानक लेआउट struct वस्तु के लिए एक सूचक, उपयुक्त रूप से एक reinterpret_cast का उपयोग कर परिवर्तित, अपनी प्रारंभिक सदस्य के लिए अंक (या यदि वह सदस्य थोड़ा-क्षेत्र, करने के लिए तो है जिस इकाई में यह रहता है) और इसके विपरीत।

और आपका फू मानक-लेआउट क्लास है।

तो आपकी दूसरी कास्ट सही है।

मुझे कोई गारंटी नहीं है कि पहला व्यक्ति सही है (और मैंने आर्किटेक्चर का उपयोग किया है जहां एक char के पास एक आर्किटेक्चर पर केवल एक char युक्त संरचना से कमजोर संरेखण प्रतिबंध था, यह समस्याग्रस्त हो जाएगा)। मानक गारंटी यह है कि यदि आपके पास int के लिए पॉइंटर है जो वास्तव में संरचना के पहले तत्व को इंगित करता है, तो आप इसे संरचना में पॉइंटर पर फिर से परिभाषित कर सकते हैं।

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

+0

क्या इसका मतलब यह है कि संरचना के शुरुआती सदस्य की तुलना में अधिक सख्त संरेखण नहीं हो सकता है? यदि हां, तो क्या इसका मतलब यह है कि संरचना के पॉइंटर्स कम से कम 'char *' के रूप में चौड़े होना चाहिए? – avakar

+0

ओह, और एकमात्र उत्तर के लिए +1 जो वास्तव में मानक को उद्धृत करता है। – avakar

+0

@avakar, ओह, मैंने पहले उदाहरण को गलत तरीके से पढ़ा, मैंने अपना जवाब तय कर दिया। धन्यवाद। – AProgrammer

2

फू एक सादा-पुरानी डेटा संरचना है, जिसका अर्थ है कि इसमें उस डेटा के अलावा कुछ भी नहीं है जिसे आप स्पष्ट रूप से स्टोर करते हैं। इस मामले में: एक int। इस प्रकार एक int और foo के लिए स्मृति लेआउट समान हैं।

आप समस्याओं के बिना एक से दूसरे में टाइपकास्ट कर सकते हैं। चाहे इस तरह के सामान का उपयोग करने के लिए यह एक चालाक विचार है, एक अलग सवाल है।

पुनश्च: यह आमतौर पर काम करता है, लेकिन जरूरी नहीं कि अलग संरेखण प्रतिबंधों की वजह से नहीं। एप्रोग्रामर का जवाब देखें।

+0

लेकिन ... 'reinterpret_cast'? वास्तव में? –

+0

@Mrlister: 'reinterpret_cast' के साथ क्या गलत है? यह वास्तव में इस तरह की चीजों के लिए है - एक चीज को एक दूसरे के रूप में दोहराएं। – Xeo

+1

मानक के लिए आवश्यक है कि पीओडी संरचना के लिए सूचक पॉइंटर के पहले तत्व के समान होता है। – spraff

4

जब तक आप केवल संरचना के पहले तत्व तक पहुंचते हैं, इसे सुरक्षित माना जाता है, क्योंकि संरचना के पहले सदस्य से पहले कोई पैडिंग नहीं होती है। वास्तव में, इस चाल उदाहरण के लिए प्रयोग किया जाता है,, Objecive-सी क्रम है, जहां एक सामान्य सूचक प्रकार के रूप में परिभाषित किया गया है में:

typedef struct objc_object { 
    Class isa; 
} *id; 

और क्रम में, असली objecs (जो अभी भी नंगे struct संकेत दिए गए हैं) स्मृति इस तरह के लेआउट:

struct { 
    Class isa; 
    int x; // random other data as instance variables 
} *CustomObject; 

और रनटाइम इस विधि का उपयोग कर वास्तविक वस्तु के वर्ग तक पहुंचता है।

+1

वह तकनीक पुरानी अमीगा पर [BOOPSI] (http://en.wikipedia.org/wiki/BOOPSI) में उपयोग की गई थी। –

+0

आप तकनीकी रूप से सही हैं, लेकिन आपने केवल आधे प्रश्न का उत्तर दिया है। – avakar

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