SwiftでC共用体型を宣言して使用するにはどうすればよいですか?
私は試した:
var value: union {
var output: CLongLong
var input: [CInt]
}
しかし、それは機能しません...
更新:和集合を使用して8 bytes number
を2x 4 bytes number
に分割したい。
Apple Swift document、 Enumerations は、同様のことなどを行うことができます。
あるいは、
enumeration
メンバーは、他の言語のunions
またはvariants
と同様に、さまざまなメンバー値とともに格納される任意のタイプの関連値を指定できます。関連するメンバーの共通セットを1つの列挙の一部として定義できます。各列挙には、適切なタイプの異なる値のセットが関連付けられています。
1)ご存知かもしれませんが、8バイトの数値を2 x 4バイトの数値に分割したい場合は、 ビット演算 of Swiftが役立ちます。お気に入り
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
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
Swiftは、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バイト(1つの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つを変更すると、a.oneField
の元の値が1,234,567,890,987,654,32に変更されることがわかります。2 予想通り。
私にとって醜い部分は、「unsafe」、「pointer」、.memory.
という単語の出現と、Xcode7.2のコンパイラエラーを克服するためだけにあるaddressOf
ヘルパー関数です。
おそらく、このようなバイトレベルの操作を必要とする低レベルの構造での作業は、Swiftのような高レベルの言語で行うべきではありません。プロジェクトのこの部分をで書くことを検討しましたか。 cファイル?適切なブリッジヘッダーを使用すると、プロジェクトの大部分をSwiftで実行できます。
そうですね、ObjCコードの構造体でCユニオンを作成でき、Swiftにインポートすると、想定どおりに動作します。ソース: https://developer.Apple .com/documentation/Swift/imported_c_and_objective-c_apis/using_imported_c_structs_and_unions_in_Swift
"SwiftはCユニオンをSwift構造体としてインポートします。Swiftはネイティブに宣言されたユニオンをサポートしていませんが、CユニオンはSwift構造は依然としてCユニオンのように動作します。」
ここでは、MyUnion
とf
という名前の2つのメンバーを持つ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
ユニオンは構造のタイプを指定していないので、常にコンテキストから派生していると思います(値がoutput
またはinput
のどちらであるかは常にわかります)。その場合、私はそれを2つの別々の構造体に変換します。
struct OutputValue {
...
}
struct InputValue {
...
}
構造体にいくつかの共通のプロパティ/メソッドを持たせたい場合は、protocol
を宣言します。