The memory layout of a type, describing its size, stride, and alignment
@frozen enum MemoryLayout<T>
static var size: Int - The contiguous memory footprint of T, in bytes.
static var alignment: Int - The default memory alignment of T, in bytes.
static var stride: Int - The number of bytes from the start of one instance of T to the start of the next when stored in contiguous memory or in an Array.
可以理解为Swift下的sizeof, 对内存理解的抽象。
MemoryLayout<Int>.size // returns 8 (on 64-bit)
MemoryLayout<Int>.alignment // returns 8 (on 64-bit)
MemoryLayout<Int>.stride // returns 8 (on 64-bit)
MemoryLayout<Int16>.size // returns 2
MemoryLayout<Int16>.alignment // returns 2
MemoryLayout<Int16>.stride // returns 2
MemoryLayout<Bool>.size // returns 1
MemoryLayout<Bool>.alignment // returns 1
MemoryLayout<Bool>.stride // returns 1
MemoryLayout<Float>.size // returns 4
MemoryLayout<Float>.alignment // returns 4
MemoryLayout<Float>.stride // returns 4
MemoryLayout<Double>.size // returns 8
MemoryLayout<Double>.alignment // returns 8
MemoryLayout<Double>.stride // returns 8
MemoryLayout<String>.size
MemoryLayout<String>.alignment
MemoryLayout<String>.stride
struct EmptyStruct { }
MemoryLayout<EmptyStruct>.size // returns 0
MemoryLayout<EmptyStruct>.alignment // returns 1
MemoryLayout<EmptyStruct>.stride // returns 1
struct SampleStruct {
let number: UInt32
let flag: Bool
}
MemoryLayout<SampleStruct>.size // returns 5
MemoryLayout<SampleStruct>.alignment // returns 4
MemoryLayout<SampleStruct>.stride // returns 8
class EmptyClass {}
MemoryLayout<EmptyClass>.size // returns 8 (on 64-bit)
MemoryLayout<EmptyClass>.stride // returns 8 (on 64-bit)
MemoryLayout<EmptyClass>.alignment // returns 8 (on 64-bit)
class SampleClass {
let number: Int64 = 0
let flag = false
}
MemoryLayout<SampleClass>.size // returns 8 (on 64-bit)
MemoryLayout<SampleClass>.stride // returns 8 (on 64-bit)
MemoryLayout<SampleClass>.alignment // returns 8 (on 64-bit)
Version: Swift 5.6, macOS 12.3, Xcode 11
Unsafe Swift - WWDC20
Benefits of unsafe interfaces:
观点:
x!
, 假设x为nil,程序会终止,这是一个预先的设计Unsafe Pointers
对应关系:
举例:
// C: `void process_integers(const int *start, size_t count);
// Swift:
func process_integers(_ start: UnsafePointer<CInt>!, _ count: Int)
// client
Buffer Pointer
Buffer Pointer = Pointer + capacity
Temporary pointers to Swift values
Generated pointer is only valid for the duration of the closure’s execution
// C:
void process_integers(const int *start, size_t count);
// Swift:
就是因为需要频繁传递buffer指针给C,所以swift专门设计了特殊语法,👍
// C:
// Swift:
隐式转换来了,兄弟
再来看一个String的例子:
Unsafe Swift | raywenderlich
MemoryLayout
@frozen enum MemoryLayout<T>
可以理解为Swift下的sizeof, 对内存理解的抽象。
从上述的描述也能反应Struct是value object, Class是reference object.
Pointer
Java, Javascript等高级语言一般工作在一个Safe的模式下,原则上是无法获取内存地址,Swift本身就是编译型语言,而且也必须兼容C/ObjC,所以Unsafe是必不可少,所以Swift提供了一组UnsafePointer来做C对应。
选择UnsafePointer需要做3个选择:
uint32_t *ptr = malloc(sizeof(uint32_t)*2);
加上Type
Unsafe memory pointers in Swift - The.Swift.Dev.
对应的swift:
Data
对
char* buffer
的抽象。Data和Array的区别:Data用来表达byte buffer,但Data是Immutable,虽然有MutableData,这单说,所以Data更多的是用来做持久化和传递,而Array因为内存layout和C一致,是一个Swift基础对象,内存透明,所以可以直接withUnsafePointer。
此外注意一个坑,
这句看上去没问题,但其实是错误的,Data的第一个bytes参数是一个UnsafeRawPointer, 然后第二个count参数单位是byte (
The number of bytes to copy.
)正确的写法:
Data+Extension.swift
UnsafeRawBufferPointer
重点参考: 在 Swift 裡頭操作 Bytes | zonble
参考内容