web-dev-qa-db-ja.com

SwiftのC共用体タイプ?

SwiftでC共用体型を宣言して使用するにはどうすればよいですか?

私は試した:

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

しかし、それは機能しません...

更新:和集合を使用して8 bytes numberを2x 4 bytes numberに分割したい。

15
zendobk

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
14
Eric Tsui

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
3
Amit89

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で実行できます。

3
Fred Truter

そうですね、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ユニオンのように動作します。」

1
Fernando Mazzon

ここでは、MyUnionfという名前の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
1
DawnSong

ユニオンは構造のタイプを指定していないので、常にコンテキストから派生していると思います(値がoutputまたはinputのどちらであるかは常にわかります)。その場合、私はそれを2つの別々の構造体に変換します。

struct OutputValue {
    ...
}

struct InputValue {
    ...
}

構造体にいくつかの共通のプロパティ/メソッドを持たせたい場合は、protocolを宣言します。

0
Sulthan