Swift 中的 C 联合类型?

C union type in Swift?

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

我试过了:

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

但是没用...

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

嗯,在 Swift 中没有联合的直接支持,但我们可以使用枚举来实现我们的目的。

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.0

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

Alternatively, enumeration members can specify associated values of any type to be stored along with each different member value, much as unions or variants do in other languages. You can define a common set of related members as part of one enumeration, each of which has a different set of values of appropriate types associated with it.

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) 如果你想像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

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

struct OutputValue {
    ...
}

struct InputValue {
    ...
}

如果您希望结构具有一些共同的 properties/methods,请为其声明一个 protocol

Swift 不鼓励像 union 这样的 "unsafe" 编程模式,但是,有一个解决方法。它有点难看,但这里是(使用 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 这将 return 初始值 1,234,567,890,987,654,321 并且 a.variantB.memory.firstField 将 return 2,976,652,465 和 a.variantB.memory.secondField 将 return 287,445,236。

我们可以像这样更改其中一个组件 a.variantB.memory.firstField++ 然后观察到这会将 a.oneField 的原始值更改为 1,234,567,890,987,654,322 作为预期。

对我来说丑陋的部分是 "unsafe"、"pointer" 和 .memory. 以及 addressOf 辅助函数的出现,它只是为了克服Xcode 7.2!

中的编译器错误

也许根本不应该使用像 Swift 这样的高级语言来处理需要像这样 byte-level 操作的 lower-level 结构。您是否考虑过将项目的这一部分写在 .c 文件中?使用合适的桥接头,您仍然可以在 Swift.

中完成大部分项目

这里我定义了MyUnion,它有两个成员fg。如您所见,union 是不安全的,带有关联值的 enum 是首选,尽管它与 union.

有点不同
// Simulate union of the C programming language
// 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

好吧,您可以在 ObjC 代码的结构中创建一个 C 联合,当在 swift 中导入时,它会像预期的那样运行。资料来源:https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/using_imported_c_structs_and_unions_in_swift

"Swift imports C unions as Swift structures. Although Swift doesn’t support natively declared unions, a C union imported as a Swift structure still behaves like a C union."