Sonntag, Dezember 8, 2019

C union-Typ in Swift?

Wie kann ich erklären, und verwenden Sie eine C-union-Typ in Swift?

Habe ich versucht:

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

aber es funktioniert nicht…

AKTUALISIERT: will ich mit union zu Spalten 8 bytes number 2 x 4 bytes number.

  • Es gibt keine direkte Unterstützung von Gewerkschaften in den Swift, aber Sie verwenden können, enumeration, um erreichen Ihre Anforderung.
  • Gewerkschaften sind disfavoured, die von fast jeder C und C++ coding standard kennen zu Mann, weil Sie so Häufig zum schreiben von nicht-portablen code. Wenn Sie eine Wahl in der Angelegenheit, nie mit einem union in C und in allen Fällen entpacken was auch immer Daten mit bit-wise Operatoren.
  • Ich würde nicht einverstanden mit Ihrer Prämisse. Zum Beispiel beim Empfang einer Nachricht, wobei die Nachricht kann eine beliebige von mehreren verschiedenen Formaten, ist es fast immer umgesetzt werden, da eine union von jenen Formaten, in der Regel, wo die erste, nicht-header-Feld gibt die Art der Meldung enthalten ist, in den rest der Nachricht, wo der rest der Nachricht ist definiert als die Vereinigung aller Nachrichtentypen.
  • Dies ist genau das Szenario, welches ich gedacht habe. durch die Verwendung einer union hier versuchen wir zu überlagern, die ein Speicher-layout auf einer Byte – für-Instanz, empfangen von dem Netzwerk, oder einem anderen Prozess. Die Portabilität Gefahren sind unzählige, weil der Ausrichtung, Struktur, Verpackung und endianness unterschiedlicher Architekturen auf einem anderen.
  • Es gibt bessere Möglichkeiten in solchen Situationen. In OOP-Sprachen, die Sie verwenden würden, Vererbung, jeden message-Typ, dargestellt durch eine andere Klasse, in C können Sie pseudo-Vererbung.
InformationsquelleAutor Dao Nguyen | 2015-06-21

6 Kommentare

  1. 16

    Als die Apple-Swift-Dokument , Enumerationen tun können, ähnliches und mehr.

    Alternativ enumeration Mitglieder können geben Sie die zugehörigen Werte von
    jeglicher Art werden gespeichert, zusammen mit jedem einzelnen Wert, wie viel
    unions oder variants tun in anderen Sprachen. Sie können definieren einen gemeinsamen Satz
    verwandter Elemente als Teil einer Aufzählung, die jeweils ein
    unterschiedliche Werte der entsprechenden Typen zugeordnet.

    1), Wenn Sie nur wollen, um split eine 8 Byte Zahl auf 2 x 4-Byte-zahlen, wie Sie vielleicht bekannte, die Bitweise Operation von Swift könnte helfen. Wie

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

    2) Wenn Sie simulieren möchten die union Verhalten, wie die C Sprache,
    Ich habe versucht, einen Weg wie diese. Obwohl es funktioniert, es sieht schrecklich aus.

    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
    • (2) ist nicht wie eine C-union an alle, es ist nur die Umwandlung zwischen double und int. Eine C-union hätten beide vars teilen die gleiche Speicheradresse, so dass die Speicherung der 8-Byte Double(5.078) nimmt und Lesen Sie wieder als Int würde nicht zurück 5, aber 0x40144FDF3B645A1D (4,617,403,338,154,334,749, Huch!)
    • Semantisch IST es ähnlich wie union. Die Gewerkschaften bedeuten, die teilen sich eine Stelle im Speicher. Eine rasche enum tut dies, außer dass es fügt auf einer byte-für den enum-Wert.
  2. 3

    Gut, es ist keine direkte Unterstützung der Gewerkschaften, in Swift, aber wir verwenden können, enumeration, die für unsere Zwecke.

    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
    • Scheint nicht den gleichen Zweck, ich möchte teilen Sie eine 8 bytes number 2 x 4 bytes numbers
    • Das ist eine unsichere operation, die absichtlich nicht unterstützt Swift. Jetzt offensichtlich, was Sie tun möchten, ist einfach zu erreichen mit shift und bitweise und-Operationen. Eine Rasche Aufzählung wird nie lassen, Sie zu re-interpretieren Daten auf eine andere Weise. Voll beabsichtigt.
  3. 3

    Swift rät „unsichere“ Programmierung Muster wie union gibt es jedoch einen workaround. Es ist ein bisschen hässlich, aber der hier geht (mit 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)
            }
        }
    }

    Nun eine schnelle überprüfung der sizeof(VariantA) zeigt die gesamte Struktur noch dauert, bis nur noch acht bytes (das ist eine 64-bit-Ganzzahl). Wenn wir jetzt eine Instanz erstellen, wie dies var a = VariantA(oneField: 1234567890987654321) dann können wir die Abfrage der Komponenten, wie diese a.oneField wird wieder der anfängliche Wert 1,234,567,890,987,654,321 und auch a.variantB.memory.firstField zurück 2,976,652,465 und a.variantB.memory.secondField zurück 287,445,236.

    Können wir ändern eine der Komponenten, wie diese a.variantB.memory.firstField++ und dann beobachten Sie, dass diese änderungen den ursprünglichen Wert von a.oneField zu 1,234,567,890,987,654,322 als erwartet.

    Die hässlichen Teile für mich sind die vorkommen der Wörter „unsicher“, „Zeiger“ und .memory. sowie addressOf Hilfsfunktion, die ist nur dazu da, um überwunden werden zu einem compiler-Fehler in Xcode 7.2!

    Vielleicht arbeiten mit Low-level-Strukturen, die erfordern, dass auf byte-Ebene manipulation wie sollte dies nicht getan werden in einer Hochsprache wie Swift überhaupt. Haben Sie sich überlegt zu schreiben, diesen Teil Ihres Projekts in einem .c-Datei? Mit einem geeigneten bridging-header können Sie immer noch die Mehrheit der Ihr Projekt in Swift.

  4. 1

    Hier definiere ich MyUnion die zwei member mit dem Namen f und g. Wie Sie sehen können, union ist unsicher, und enum mit den zugehörigen Wert ist bevorzugt, obwohl es ein bisschen anders aus 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
  5. 1

    Gut, können Sie eine C-union in eine Struktur, die in ObjC-code, und die beim Import in swift wird es sich Verhalten wie es soll. Quelle: https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/using_imported_c_structs_and_unions_in_swift

    „Swift Einfuhren C-Gewerkschaften, die als Swift-Strukturen. Obwohl Swift nicht nativ unterstützen, erklärte Gewerkschaften, die ein C in die union eingeführten Swift-Struktur, noch verhält sich wie eine C-union.“

  6. 0

    Ihre union nicht geben Sie den Typ der Struktur, so würde ich davon ausgehen, Sie sind immer ableiten, dass aus dem Kontext (wissen Sie immer, wenn der Wert entweder output oder input). In diesem Fall würde ich es übersetzen in zwei separate Strukturen:

    struct OutputValue {
        ...
    }
    
    struct InputValue {
        ...
    }

    Wenn Sie wollen, dass die Strukturen haben einige gemeinsame Eigenschaften/Methoden deklarieren Sie eine protocol für Sie.

Kostenlose Online-Tests

Letzte Fragen

Tun ItemView löst Blase?

Ich habe eine CompositeView für eine Tabelle. Ich habe Trigger-set in der Kind-ItemView für jede Zeile... var TableRow = Marionette.ItemView.extend({ tagName:...

Wie kann ich untersuchen, WCF was 400 bad request über GET?

Die folgenden WCF-endpoint funktioniert gut mit dem WCF test client: AssetList ListFlaggedAssets(short processCode, string platform, string endpoint = "null", string portalId = "null", int...

Bei der Verwendung von UUIDs, sollte ich auch mit AUTO_INCREMENT?

Wir bauen eine neue web-app, die eine offline-iPad - /Android-app-version auf einer Reihe von lokalen Geräten, die Einsätze mit neuen Daten. Als solche benötigen...

Actionscript-Objekt, das verschiedene Eigenschaften

Wie kann ich die Anzahl der Eigenschaften in einer generischen Actionscript-Objekt? (Wie die Array-Länge) InformationsquelleAutor Fragsworth | 2011-01-15

Wie plot mehrere Graphen und nutzen Sie die Navigations-Taste im [matplotlib]

Die neueste version von matplotlib erstellt automatisch Navigations-buttons unter den graph. Aber die Beispiele, die ich finden alles im Internet zeigen, wie erstellen Sie...