संरचनाओं में सुरक्षित अतिव्यापी / संघ क्षेत्र बनाना

Aug 16 2020

C ++ में, मैं इन जैसी संरचनाएँ बना सकता हूँ:

union Vector4
{
    struct { float x, y, z, w; };
    float data[4];
};

इसलिए मैं आसानी से फ़ील्ड के रूप में या एक सन्निहित सरणी के रूप में डेटा तक पहुंच सकता हूं। वैकल्पिक रूप से, मैं केवल पहले फ़ील्ड में एक पॉइंटर बना सकता हूं xऔर पॉइंटर से एक सन्निहित सरणी के रूप में पढ़ सकता हूं ।

मुझे पता है कि एनम हैं, लेकिन मैं अतिरिक्त ओवरहेड के लिए भुगतान नहीं कर सकता। मुझे यह भी पता है कि मैं रस्ट में यूनियनों का निर्माण कर सकता हूं, लेकिन उन्हें मुझे अपना कोड लिटर करने की आवश्यकता है unsafeजहां कभी मैं उन्हें एक्सेस कर रहा हूं। जो मुझे लगता है कि मुझे नहीं करना चाहिए क्योंकि कोड असुरक्षित नहीं है क्योंकि अंतर्निहित डेटा को हमेशा फ्लोट के रूप में दर्शाया जाता है (और मुझे सी-लेआउट की आवश्यकता है #[repr(C)]ताकि कंपाइलर खेतों के आदेश के आसपास फेंक न दें)।

मैं इसे रस्ट में कैसे लागू करूंगा ताकि मैं नाम से खेतों तक पहुंच पाऊं लेकिन पूरे ढांचे की आकस्मिक स्मृति तक आसान और सुरक्षित पहुंच हो? यदि यह संभव नहीं है, तो क्या कोई तरीका है ताकि मैं सुरक्षित रूप से एक संरचना का टुकड़ा ले सकूं?

जवाब

3 Locke Aug 17 2020 at 00:08

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

यह कहा जा रहा है, यहाँ मेरी पूरी तरह से 100% एक संघ नहीं है Vector4। जैसा कि आप देख सकते हैं, Derefअसुरक्षित कोड को छिपाने के लिए काम करता है और इसे बनाता है ताकि आप Vector4या तो इसका उपयोग उस संदर्भ के आधार पर एक संरचना या एक सरणी के रूप में कर सकते हैं । प्रसारण भी आदर्श नहीं है, लेकिन मुझे लगता है कि मैं इसे सही ठहरा सकता हूं इस मामले में। यदि आप ऐसा कुछ करना चुनते हैं, तो आप भी इसे लागू करना चाह सकते हैं DerefMut

use std::ops::Deref;

// I'm not sure if the repr(C) is needed in this case, but I added it just in case.
#[repr(C)]
pub struct Vector4<T> {
    pub x: T,
    pub y: T,
    pub z: T,
    pub w: T,
}

impl<T> Deref for Vector4<T>
where
    T: Copy + Sized,
{
    type Target = [T; 4];

    fn deref(&self) -> &Self::Target {
        use std::mem::transmute;
        unsafe { transmute(self) }
    }
}

pub fn main() {
    let a = Vector4{
        x: 37,
        y: 21,
        z: 83,
        w: 94,
    };

    println!("{:?}", &a[..]);
    // Output: [37, 21, 83, 94]
}