2015-06-21 3 views
8

स्विफ्ट में सी यूनियन प्रकार की घोषणा और उपयोग कैसे कर सकता हूं?सी यूनियन प्रकार?

मैंने कोशिश की:

var value: union { 
     var output: CLongLong 
     var input: [CInt] 
    } 

लेकिन यह काम नहीं करता ...

UPDATED: मैं एक 8 bytes number 2 एक्स 4 bytes number को विभाजित करने के लिए संघ का उपयोग करना चाहते।

+0

स्विफ्ट में यूनियनों का कोई प्रत्यक्ष समर्थन नहीं है, लेकिन आप अपनी आवश्यकता को पूरा करने के लिए गणना का उपयोग कर सकते हैं। – Amit89

+2

यूनियनों को केवल हर सी और सी ++ कोडिंग मानक द्वारा मनुष्यों को पता चला है क्योंकि उन्हें गैर-पोर्टेबल कोड लिखने के लिए अक्सर उपयोग किया जाता है। यदि आपके पास इस मामले में कोई विकल्प है, तो कभी भी सी में 'यूनियन' का उपयोग न करें, और सभी मामलों में बिट-वार ऑपरेटरों के साथ जो भी डेटा शामिल है, उसे अनपैक करें। – marko

+0

@marko, मुझे आपके आधार से असहमत होना होगा। उदाहरण के लिए, संदेश प्राप्त करते समय, जहां संदेश में कई अलग-अलग प्रारूप हो सकते हैं, यह लगभग हमेशा उन प्रारूपों के संघ के रूप में लागू होता है, आमतौर पर जहां पहला, गैर हेडर, फ़ील्ड इंगित करता है कि शेष संदेश किस प्रकार का है संदेश, जहां शेष संदेश सभी संदेश प्रकारों के संघ के रूप में परिभाषित किया गया है। – user3629249

उत्तर

10

एप्पल स्विफ्ट दस्तावेज़ के रूप में, Enumerations समान बात और कुछ कर सकते हैं।

वैकल्पिक रूप से, enumeration सदस्यों किसी भी प्रकार की संबद्ध मानों प्रत्येक अलग सदस्य मूल्य के साथ साथ संग्रहीत करने के लिए, बहुत द्वारा बताए गए अनुसार unions या variants अन्य भाषाओं में कर सकते हैं। आप एक गणना के हिस्से के रूप में संबंधित सदस्यों के एक सामान्य सेट को परिभाषित कर सकते हैं, जिनमें से प्रत्येक के पास इसके साथ जुड़े उचित प्रकार के मानों के विभिन्न सेट हैं।

1) तुम सिर्फ, 2 एक्स 4 बाइट्स संख्या के लिए एक 8 बाइट्स संख्या विभाजित करने के लिए के रूप में आप में जाना जाता है हो सकता है चाहते हैं, स्विफ्ट की Bitwise Operation मदद कर सकता है। बस

let bigNum: UInt64 = 0x000000700000008 // 
let rightNum = (bigNum & 0xFFFFFFFF) // output 8 
let leftNum = (bigNum >> 32) // output 7 

2) आप C भाषा की तरह union व्यवहार अनुकरण करने के लिए चाहते हैं, की तरह मैं इस तरह एक तरह से कोशिश की। हालांकि यह काम करता है, यह भयानक लग रहा है।

enum Number { 
    case a(Int) 
    case b(Double) 

    var a:Int{ 
     switch(self) 
     { 
     case .a(let intval): return intval 
     case .b(let doubleValue): return Int(doubleValue) 
     } 
    } 

    var b:Double{ 
     switch(self) 
     { 
     case .a(let intval): return Double(intval) 
     case .b(let doubleValue): return doubleValue 
     } 
    } 
} 
let num = Number.b(5.078) 

println(num.a) // output 5 
println(num.b) // output 5.078 
+3

(2) एक सी यूनियन की तरह नहीं है, यह सिर्फ डबल और int के बीच परिवर्तित हो रहा है। एसी यूनियन में दोनों वर्र्स समान स्मृति स्थान साझा करेंगे, इसलिए 8 बाइट्स डबल (5.078) को स्टोर करना और उन्हें वापस पढ़ना एक इंटेल के रूप में वापस नहीं लौटाएगा, लेकिन 0x40144FDF3B645A1D (4,617,403,338,154,334,749, yikes!) – GoatInTheMachine

+0

अर्थात्, यह समान है संघ। यूनियनों का मतलब स्मृति में एक जगह साझा करना है। एक तेज़ enum यह करता है, सिवाय इसके कि यह enum मूल्य के लिए एक बाइट जोड़ता है। –

2

ठीक है, स्विफ्ट में यूनियनों का कोई प्रत्यक्ष समर्थन नहीं है, लेकिन हम अपने उद्देश्य के लिए गणना का उपयोग कर सकते हैं।

पूर्व-

enum Algebra { 
    case Addition(Double, Double) 
    case Substraction(Double, Double) 
    case Square(Double) 

    var result : Double { 
    switch(self) 
    { 
    case .Addition(let a, let b): return a + b 
    case .Substraction(let a, let b): return a - b 
    case .Square(let a): return a * a 
    } 
    } 
} 

let solution = Algebra.Addition(5, 3) 
println(solution.result) //Output: 8.0 
+0

एक ही उद्देश्य नहीं लगता है, मैं एक '8 बाइट्स संख्या' को 2 x '4 बाइट्स संख्या –

+2

विभाजित करना चाहता हूं यह एक असुरक्षित ऑपरेशन है जिसे जानबूझकर स्विफ्ट में समर्थित नहीं है। अब स्पष्ट रूप से आप जो करना चाहते हैं वह बदलाव और बिटवाई और संचालन के साथ प्राप्त करने के लिए तुच्छ है। एक स्विफ्ट गणना _never_ आपको डेटा को एक अलग तरीके से दोबारा व्याख्या करने देगी। पूरी तरह से जानबूझकर। – gnasher729

0

आपका संघ संरचना के प्रकार को निर्दिष्ट नहीं करता, तो मैं आप हमेशा पाने रहे हैं कि संदर्भ से (आप कभी भी अगर यह मान output या input है) ग्रहण करेंगे। उस मामले में, मैं इसे दो अलग-अलग structs में अनुवाद होगा:

struct OutputValue { 
    ... 
} 

struct InputValue { 
    ... 
} 

आप structs, कुछ सामान्य गुण/तरीकों इसके लिए एक घोषित करने के लिए चाहते हैं।

2

स्विफ्ट union जैसे "असुरक्षित" प्रोग्रामिंग पैटर्न को हतोत्साहित करता है, हालांकि, एक कामकाज है। यह एक सा बदसूरत है, लेकिन यहां (Xcode 7.2 का प्रयोग करके) जाता है ...

struct VariantA { 
    var oneField: Int // 8 bytes 

    struct VariantB { 
     var firstField: UInt32 // first 4 bytes 
     var secondField: UInt32 // second 4 bytes 
    } 

    var variantB: UnsafeMutablePointer<VariantB> { 
     mutating get { 
      func addressOf<U>(something:UnsafePointer<U>) 
       -> UnsafeMutablePointer<VariantB> { 
       return UnsafeMutablePointer<VariantB>(something) 
      } 
      return addressOf(&oneField) 
     } 
    } 
} 

अब sizeof(VariantA) की एक त्वरित जांच (जो एक 64-बिट पूर्णांक) दिखाएगा पूरी संरचना अभी भी केवल आठ बाइट्स लेता है। अगर हम अब इस var a = VariantA(oneField: 1234567890987654321) जैसे उदाहरण बनाते हैं तो हम इस a.oneField जैसे घटकों से पूछ सकते हैं जो प्रारंभिक मान 1,234,567,890,987,654,321 और a.variantB.memory.firstField वापस कर देंगे 2,976,652,465 और a.variantB.memory.secondField वापस 287,445,236 लौटाएंगे।

हम इस a.variantB.memory.firstField++ तरह घटकों में से एक को बदल सकते हैं और उसके बाद देख सकते हैं कि इस 1,234,567,890,987,654,32 करने के लिए a.oneField के मूल मूल्य में परिवर्तन के रूप में उम्मीद।

मेरे लिए बदसूरत भाग "असुरक्षित", "सूचक" और .memory. शब्दों के साथ-साथ addressOf सहायक फ़ंक्शन जो एक्सकोड 7.2 में एक कंपाइलर त्रुटि को दूर करने के लिए केवल वहां हैं!

शायद निम्न स्तर की संरचनाओं के साथ काम करना जिसके लिए बाइट-स्तरीय हेरफेर की आवश्यकता होती है, इसे स्विफ्ट जैसी उच्च स्तरीय भाषा में नहीं किया जाना चाहिए। क्या आपने अपनी परियोजना के इस हिस्से को .c फ़ाइल में लिखने पर विचार किया है? एक उपयुक्त ब्रिजिंग हेडर के साथ आप अभी भी स्विफ्ट में अपनी अधिकांश परियोजनाएं कर सकते हैं।

1

यहां मैं MyUnion परिभाषित करता हूं जिसमें दो सदस्य हैं f और g। जैसा कि आप देख सकते हैं, union असुरक्षित है, और enum संबंधित मान के साथ पसंदीदा है, हालांकि यह union से थोड़ा अलग है।

// Simulate union in C 
// f and g share memory 
struct MyUnion { 
    fileprivate var ivar: UInt32 = 0 // Shared memory, private is better. 

    var f: Float { 
     get { return Float.init(bitPattern: ivar) } 
     set { ivar = newValue.bitPattern } 
    } 
    init(f: Float) { self.f = f } 

    var g: Int32 { 
     get { return Int32(bitPattern: ivar) } 
     set { ivar = UInt32(bitPattern: newValue) } 
    } 
    init(g: Int32) { self.g = g } 
} 

var u = MyUnion(f: 13.12) 
u.f // 13.12 
u.g // 1095887749 
u.ivar // 1095887749 

u.f = -99.123 
u.f // -99.123 
u.g // -1027195142 
u.ivar // 3267772154 

u = MyUnion(g: -1) 
u.f // nan 
u.g // -1 
u.ivar // 4294967295 
संबंधित मुद्दे