Swift中的C联合类型?

时间:2015-06-21 07:55:39

标签: c swift unions

如何在Swift中声明和使用C union类型?

我试过了:

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

但它不起作用......

更新:我想使用union将8 bytes number拆分为2 x 4 bytes number

6 个答案:

答案 0 :(得分:12)

作为Apple Swift文档,Enumerations可以做类似的事情。

  

或者,enumeration成员可以指定相关的值   任何类型与每个不同的成员值一起存储,就像   unionsvariants使用其他语言。您可以定义一个公共集   相关成员作为一个枚举的一部分,每个成员都有一个   与之相关的适当类型的不同值集。

1)如果您只想将一个8字节的数字拆分为2 x 4字节的数字,正如您可能已经知道的那样,Swift的Bitwise Operation可以提供帮助。就像

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

2)如果您想模拟union语言的C行为, 我试过这样的方式。虽然它有效但看起来很糟糕。

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

答案 1 :(得分:3)

嗯,在Swift中没有工会的直接支持,但我们可以使用枚举来达到我们的目的。

实施例 -

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

答案 2 :(得分:3)

斯威夫特劝阻"不安全"编程模式,如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)将显示整个结构仍然只占用8个字节(这是一个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++,然后观察这会将a.oneField的原始值更改为1,234,567,890,987,654,32 2

对我来说丑陋的部分是“不安全的”#34;,&#34;指针&#34;和.memory.以及addressOf辅助函数,它只能克服Xcode 7.2中的编译器错误!

也许使用像这样需要字节级操作的低级结构不应该像Swift这样的高级语言来完成。您是否考虑过在.c文件中编写项目的这一部分?使用合适的桥接头,您仍然可以在Swift中完成大部分项目。

答案 3 :(得分:1)

我在此定义MyUnion,其中有两个成员名为fg。正如您所看到的,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

答案 4 :(得分:0)

你的联盟没有指定结构的类型,所以我假设你总是从上下文中得到它(你总是知道值是output还是input) 。在这种情况下,我会将其翻译成两个独立的结构:

struct OutputValue {
    ...
}

struct InputValue {
    ...
}

如果您希望结构具有一些共同的属性/方法,请为其声明protocol

答案 5 :(得分:0)

好吧,您可以在ObjC代码中的结构中建立C联合,并且迅速导入时,其行为将像预期的那样。来源:https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/using_imported_c_structs_and_unions_in_swift

“ Swift将C联合作为Swift结构导入。尽管Swift不支持本地声明的联合,但是作为Swift结构导入的C联合的行为仍然像C联合。”