Swift: comment utiliser sizeof?

Afin de s'intégrer aux API C lors de L'utilisation de Swift, j'ai besoin d'utiliser la fonction sizeof. En C, c'était facile. Dans Swift, je suis dans un labyrinthe d'erreurs de type.

, j'ai ce code:

var anInt: Int = 5
var anIntSize: Int = sizeof(anInt)

La deuxième ligne a l'erreur "'NSNumber' n'est pas un sous-type de 'T. Type'". Pourquoi est-ce et comment puis-je le réparer?

42
demandé sur user1021430 2014-07-10 00:05:09

5 réponses

Utilisez sizeof comme suit:

let size = sizeof(Int)

sizeof utilise le type du paramètre.

Si vous voulez la taille de la variable anInt, Vous pouvez passer le champ dynamicType à sizeof.

Comme ça:

var anInt: Int = 5
var anIntSize: Int = sizeof(anInt.dynamicType)

Ou plus simplement (souligné par l'utilisateur102008):

var anInt: Int = 5
var anIntSize: Int = sizeofValue(anInt)
43
répondu wbennett 2014-07-10 20:38:43

Mise à Jour pour Swift 3

Attention à ce que MemoryLayout<T>.size signifie quelque chose de différent de sizeof en C / Obj-C. Vous pouvez lire cet ancien fil https://devforums.apple.com/message/1086617#1086617

Swift utilise un type générique pour indiquer explicitement que le nombre est connu au moment de la compilation.

Pour résumer, {[3] } est l'espace requis pour une seule instance tandis que MemoryLayout<Type>.stride est la distance entre les éléments successifs d'un tableau contigu. MemoryLayout<Type>.stride dans Swift est le même comme sizeof(type) dans C / Obj-C.

Pour donner un exemple plus concret:

struct Foo {
  let x: Int
  let y: Bool
}

MemoryLayout<Int>.size      // returns 8 on 64-bit
MemoryLayout<Bool>.size     // returns 1
MemoryLayout<Foo>.size      // returns 9
MemoryLayout<Foo>.stride    // returns 16 because of alignment requirements
MemoryLayout<Foo>.alignment // returns 8, addresses must be multiples of 8
83
répondu Ray Fix 2016-12-08 21:29:29

Swift 3 a maintenant MemoryLayout.size(ofValue:) qui peut rechercher la taille dynamiquement.

L'utilisation d'une fonction générique qui utilise à son tour MemoryLayout<Type> aura des résultats inattendus si vous lui transmettez par exemple une référence de type de protocole. C'est parce que - pour autant que je sache - le compilateur a alors toutes les informations de type dont il a besoin pour remplir les valeurs au moment de la compilation, ce qui n'est pas évident en regardant l'appel de fonction.

19
répondu Andreas 2017-08-13 22:22:45

Dans Xcode 8 avec Swift 3 beta 6 il n'y a pas de fonction sizeof (). Mais si vous le souhaitez, vous pouvez définir pour vos besoins. Cette nouvelle fonction sizeof fonctionne comme prévu avec un tableau. Cela n'était pas possible avec l'ancienne fonction sizeof intégrée.

let bb: UInt8 = 1
let dd: Double = 1.23456

func sizeof <T> (_ : T.Type) -> Int
{
    return (MemoryLayout<T>.size)
}

func sizeof <T> (_ : T) -> Int
{
    return (MemoryLayout<T>.size)
}

func sizeof <T> (_ value : [T]) -> Int
{
    return (MemoryLayout<T>.size * value.count)
}

sizeof(UInt8.self)   // 1
sizeof(Bool.self)    // 1
sizeof(Double.self)  // 8
sizeof(dd)           // 8
sizeof(bb)           // 1

var testArray: [Int32] = [1,2,3,4]
var arrayLength = sizeof(testArray)  // 16

Vous avez besoin de toutes les versions de la fonction sizeof, pour obtenir la taille d'une variable et d'obtenir la taille correcte d'un type de données et d'un tableau.

Si vous définissez seulement la deuxième fonction, alors sizeof (UInt8.Auto) et sizeof (Bool.auto) volonté résultat en "8". Si vous ne définissez que les deux premières fonctions, sizeof (testArray) donnera "8".

14
répondu j.s.com 2016-08-19 12:45:31

Swift 4

À partir de Xcode 9, Il existe maintenant une propriété appelée .bitWidth, ce qui fournit une autre façon d'écrire les fonctions sizeof: pour les instances et les types entiers:

func sizeof<T:FixedWidthInteger>(_ int:T) -> Int {
    return int.bitWidth/UInt8.bitWidth
}

func sizeof<T:FixedWidthInteger>(_ intType:T.Type) -> Int {
    return intType.bitWidth/UInt8.bitWidth
}

sizeof(UInt16.self) // 2
sizeof(20) // 8

Mais il serait plus logique pour la cohérence de remplacer sizeof: par .byteWidth:

extension FixedWidthInteger {
    var byteWidth:Int {
        return self.bitWidth/UInt8.bitWidth
    }
    static var byteWidth:Int {
        return Self.bitWidth/UInt8.bitWidth
    }
}

1.byteWidth // 8
UInt32.byteWidth // 4

Il est facile de voir pourquoi sizeof: est considéré comme ambigu mais je ne suis pas sûr que l'enterrer à MemoryLayout était la bonne chose à faire. Voir le raisonnement derrière le déplacement de sizeof: à MemoryLayout ici.

6
répondu sketchyTech 2017-11-13 12:38:33