No-payload enums 布局比較簡單,也好理解,接下來看看 Single-payload enums
Single-payload enums
enum IFLEnum {
case test_one(Bool)
case test_two
case test_three
case test_four
}
print(MemoryLayout<IFLEnum>.size)
print(MemoryLayout<IFLEnum>.stride)
打印
1
1
enum IFLEnum {
case test_one(Int)
case test_two
case test_three
case test_four
}
print(MemoryLayout<IFLEnum>.size)
print(MemoryLayout<IFLEnum>.stride)
打印
9
16
為什么都是單個負載,Swift結(jié)構(gòu)占用的內(nèi)存大小卻不一致
Swift中 Single-payload enums 會使用負載類型中的額外空間來記錄沒有負載的case值
首先 Bool 類型是1字節(jié),也就是UInt8, 所以當前能表達256種case
對于Bool來說,只需要抵用低位的0, 1這兩種情況,其余的空間就可以用來表示沒有負載的值
而對于Int來說,其實系統(tǒng)沒辦法推算當前的負載所要使用的位數(shù),也就意味著當前Int的負載是沒有額外空間的,就需要額外開辟空間存儲剩余的沒有負載的case,也就是 8+1 = 9字節(jié),對齊方式就是 Int的整數(shù)倍 16字節(jié)
Single-payload - Bool, 5個變量 是按照 1字節(jié)去對齊的, 大小也均為1字節(jié)
Single-payload - Bool, 5個變量 是按照 16字節(jié)去對齊的, 大小也均為16字節(jié)的前9個字節(jié)
小端模式讀取
0x0a =========> 10
0x14 =========> 20
第三行 0x01 00 00 00 00 00 00 00 00
最后兩行 高位也都是 0x01
高位1字節(jié)01 標識 未負載case, 剩余3個變量 低位 分別是 0 1 2
多個負載 Mutil-payload enums
enum IFLEnum {
case test_one(Bool)
case test_two
case test_three(Bool)
case test_four
}
print(MemoryLayout<IFLEnum>.size)
print(MemoryLayout<IFLEnum>.stride)
打印
1
1
6個枚舉變量在內(nèi)存中的存儲 : 01 00 80 41 40 81 大小1字節(jié),1字節(jié)對齊
用更多成員枚舉 對照測試打印
發(fā)現(xiàn)多負載 枚舉 的規(guī)律
有負載case,始終用低位 0標識false 1標識 true, 其余位中選擇一位標識哪個case
其余的case 按照成員case順序, 低位 順序0,接著1,高位偶數(shù)階遞增
這個規(guī)律需要進一步 swift源碼探究驗證
多負載枚舉大小
enum IFLEnum {
case test_one(Bool)
case test_two
case test_three(Int)
case test_four
case test_five
case test_six
case test_seven
case test_eight
case test_nine
}
print(MemoryLayout<IFLEnum>.size)
print(MemoryLayout<IFLEnum>.stride)
打印
9
16
Int 占8字節(jié),Bool 1字節(jié)低位 0或1標識,占用1位, UInt8 能表示256種case,其余空間可分配給剩下的case使用,總共需要9個字節(jié)
對齊按照最大占用字節(jié)的倍數(shù) 8 * 2 = 16字節(jié) 對齊
這就解答了 上一篇 swift枚舉(一) 中的一個遺留問題
enum IFLEnum {
case circle(Double)
case rectangle(Int, Int)
case triangle(Int, Int, Int)
case none
}
print(MemoryLayout<IFLEnum>.size)
print(MemoryLayout<IFLEnum>.stride)
結(jié)果
25 ---- triangle負載 3個Int 也就是3個8字節(jié),rectangle負載 兩個Int,復用3個Int負載 ,circle 也是8字節(jié),3個Int負載空間完全也可以復用 其余1字節(jié) 能表示256種case
32 ---- 最大占用字節(jié)數(shù) 為8字節(jié), 負載最大是3個8字節(jié),再加上 剩余1字節(jié) 補齊8字節(jié)對齊
特殊情況
enum IFLEnum {
case one
}
print(MemoryLayout<IFLEnum>.size)
print(MemoryLayout<IFLEnum>.stride)
結(jié)果
0
1
由于不需要用任何東西來區(qū)分 唯一case one,所以打印 IFLEnum結(jié)構(gòu)大小時你會發(fā)現(xiàn)是0