如何在Swift中声明和使用C union类型?
我试过了:
var value: union {
var output: CLongLong
var input: [CInt]
}
但它不起作用......
更新:我想使用union将8 bytes number
拆分为2 x 4 bytes number
。
答案 0 :(得分:12)
作为Apple Swift文档,Enumerations可以做类似的事情。
或者,
enumeration
成员可以指定相关的值 任何类型与每个不同的成员值一起存储,就像unions
或variants
使用其他语言。您可以定义一个公共集 相关成员作为一个枚举的一部分,每个成员都有一个 与之相关的适当类型的不同值集。
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
,其中有两个成员名为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
答案 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联合。”