简体   繁体   English

Swift 内存布局

[英]Swift MemoryLayout

I have a struct:我有一个结构:

struct ShortResume {
    let age: Int32
    let hasVehicle: Bool
}

When I do print(MemoryLayout<ShortResume>.size) , it prints out 5, that is correct: Int32 occupies 4 bytes and Bool occupies 1 byte.当我执行print(MemoryLayout<ShortResume>.size)时,它打印出 5,这是正确的:Int32 占用 4 个字节,Bool 占用 1 个字节。

Then I change my struct to this:然后我将我的结构更改为:

struct ShortResume {
    let age: Int32?
    let hasVehicle: Bool
}

it prints out 6, that is also correct, because optional occupies 1 byte in memory.它打印出 6,这也是正确的,因为 optional 在 memory 中占用 1 个字节。

However, when I change my struct to this:但是,当我将结构更改为此时:

struct ShortResume {
    let age: Int32?
    let hasVehicle: Bool?
}

it prints out 6 again, but it must be 7, because there are two optionals now.它再次打印出 6,但它必须是 7,因为现在有两个可选项。

Why?为什么? Maybe I'm missing something?也许我错过了什么?

If you look at如果你看

MemoryLayout<Bool?>.size

You'll see that it is actually 1. But你会看到它实际上是 1。但是

MemoryLayout<Int32?>.size

is 5 as expected.是 5 正如预期的那样。

You may know that Optional is an enum declared like this:你可能知道Optional是一个这样声明的枚举:

public enum Optional<Wrapped> {
    case none
    case some(Wrapped)

    // ...
}

So the memory needed for a T?那么T? is the memory needed for T , plus one flag bit to store whether it is none or some .T所需的 memory ,加上一个标志位来存储它是none还是some Therefore, one byte is theoretically more than necessary to store a Bool?因此,一个字节理论上比存储Bool? . .

And it turns out that Swift is actually really smart - in the current implementation, this flag can go in any unused place in the layout of T , which is why the flag and the value of the Bool are in the same byte.事实证明,Swift 实际上非常聪明——在当前的实现中,这个标志可以 go 在T布局中任何未使用的位置,这就是标志和Bool的值在同一个字节中的原因。

These are some of my experiments:这些是我的一些实验:

struct A {
    let w: Bool
    let x: Int8
    let y: Int8
    let z: Int8
}

MemoryLayout<A?>.size // 4, that flag must be in the first byte

struct B {
    let w: Int8
    let x: Bool
    let y: Int8
    let z: Int8
}

MemoryLayout<B?>.size // 4, that flag must be in the second byte

struct C {
    let w: Int8
    let x: Int8
    let y: Bool
    let z: Int8
}

MemoryLayout<C?>.size // 4, that flag must be in the third byte

struct D {
    let w: Int8
    let x: Int8
    let y: Int8
    let z: Bool
}

MemoryLayout<D?>.size // 4, that flag must be in the last byte

struct E {
    let w: Int8
    let x: Int8
    let y: Int8
    let z: Int8
}

MemoryLayout<E?>.size // 5, that flag must be in the extra byte

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM