为了在使用Swift时与C API集成,我需要使用sizeof函数。在C中,这很容易。在Swift中,我处于类型错误的迷宫中。
我有这段代码:
var anInt: Int = 5
var anIntSize: Int = sizeof(anInt)
第二行有错误"' NSNumber'不是' T.Type'"的子类型。为什么这样,我该如何解决?
答案 0 :(得分:95)
针对Swift 3进行了更新
请注意,MemoryLayout<T>.size
表示与C / Obj-C中的sizeof
不同的内容。你可以阅读这个旧帖子https://devforums.apple.com/message/1086617#1086617
Swift使用泛型类型来明确表示编号在编译时是已知的。
总而言之,MemoryLayout<Type>.size
是单个实例所需的空间,而MemoryLayout<Type>.stride
是连续数组中连续元素之间的距离。 Swift中的MemoryLayout<Type>.stride
与C / Obj-C中的sizeof(type)
相同。
举一个更具体的例子:
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
答案 1 :(得分:47)
使用sizeof如下:
let size = sizeof(Int)
sizeof
使用类型作为参数。
如果您想要anInt
变量的大小,可以将dynamicType
字段传递给sizeof
。
像这样:
var anInt: Int = 5
var anIntSize: Int = sizeof(anInt.dynamicType)
或者更简单(user102008指出):
var anInt: Int = 5
var anIntSize: Int = sizeofValue(anInt)
答案 2 :(得分:23)
Swift 3现在有MemoryLayout.size(ofValue:)
,可以动态查找大小。
如果您使用MemoryLayout<Type>
,则使用通用功能会产生意外结果传递协议类型的引用。这是因为 - 据我所知 - 然后编译器具有在编译时填充值所需的所有类型信息,这在查看函数调用时并不明显。然后,您将获得协议的大小,而不是当前值。
答案 3 :(得分:15)
在带有Swift 3 beta 6的Xcode 8中,没有函数sizeof()。但如果您愿意,可以根据自己的需要定义一个。这个新的sizeof函数与数组一起工作。使用旧的builtin sizeof函数无法做到这一点。
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
您需要sizeof函数的所有版本,以获取变量的大小并获得数据类型和数组的正确大小。
如果只定义第二个函数,那么sizeof(UInt8.self)和sizeof(Bool.self)将导致“8”。如果只定义前两个函数,那么sizeof(testArray)将产生“8”。
答案 4 :(得分:9)
Swift 4
从Xcode 9开始,现在有一个名为.bitWidth
的属性,这为实例和整数类型提供了另一种写sizeof:
函数的方法:
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
但将sizeof:
替换为.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
很容易理解为什么sizeof:
被认为含糊不清但我不确定将它埋在MemoryLayout中是正确的做法。请参阅sizeof:
转换为MemoryLayout
here背后的原因。