swift枚舉(二)

swift枚舉(一)

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é)

image.png

Single-payload - Bool, 5個變量 是按照 1字節(jié)去對齊的, 大小也均為1字節(jié)

image.png

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

image.png

6個枚舉變量在內(nèi)存中的存儲 : 01 00 80 41 40 81 大小1字節(jié),1字節(jié)對齊

image.png

用更多成員枚舉 對照測試打印

發(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

swift枚舉(三)-Optional

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容