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?
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)
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
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.
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".
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.