¿Cómo puedo declarar y usar un tipo de unión C en Swift?
Lo intenté:
var value: union { var output: CLongLong var input: [CInt] }Pero no funciona...
ACTUALIZADO: quiero usar union para dividir un número de 8 bytes number de 2 x 4 bytes number .
Como el documento de Apple Swift, las enumeraciones pueden hacer cosas similares y más.
Como alternativa, los miembros de la
enumerationpueden especificar valores asociados de cualquier tipo que se almacenarán junto con cada valor de miembro diferente, como lo hacen lasunionsovariantsen otros idiomas. Puede definir un conjunto común de miembros relacionados como parte de una enumeración, cada uno de los cuales tiene un conjunto diferente de valores de tipos apropiados asociados.
1) Si solo desea dividir un número de 8 bytes en números de 2 x 4 bytes, como ya sabrá, la operación bit a bit de Swift podría ayudar. Al igual que
let bigNum: UInt64 = 0x000000700000008 // let rightNum = (bigNum & 0xFFFFFFFF) // output 8 let leftNum = (bigNum >> 32) // output 7 2) Si desea simular el comportamiento de la union como el lenguaje C , probé una forma como esta. Aunque funciona, se ve terrible.
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.078Bueno, no hay soporte directo de uniones en Swift, pero podemos usar la enumeración para nuestro propósito.
Ex-
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.0Swift desaconseja patrones de programación "inseguros" como union , sin embargo, hay una solución. Es un poco feo, pero aquí va (usando 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) } } } Ahora, una verificación rápida de sizeof(VariantA) mostrará que toda la estructura aún ocupa solo ocho bytes (que es un número entero de 64 bits). Si ahora creamos una instancia como esta var a = VariantA(oneField: 1234567890987654321) entonces podemos consultar los componentes como este a.oneField que devolverá el valor inicial 1,234,567,890,987,654,321 y también a.variantB.memory.firstField devolverá 2,976,652,465 y a.variantB.memory.secondField devolverá 287.445.236.
Podemos cambiar uno de los componentes como este a.variantB.memory.firstField++ y luego observar que esto cambia el valor original de a.oneField a 1,234,567,890,987,654,32 2 como se esperaba.
Las partes feas para mí son las apariciones de las palabras "inseguro", "puntero" y .memory. ¡así como esa función de ayuda addressOf que solo está ahí para superar un error del compilador en Xcode 7.2!
Quizás trabajar con estructuras de nivel inferior que requieren una manipulación de nivel de byte como esta no debería hacerse en un lenguaje de alto nivel como Swift. ¿Ha considerado escribir esta parte de su proyecto en un archivo .c? Con un encabezado de puente adecuado, aún puede hacer la mayor parte de su proyecto en Swift.