站在彙編角度深入瞭解 Swift(四)

小星星_ios發表於2020-04-04

思考下面的列舉變數的記憶體佈局

enum TestEnum {
    case test1, test2, test3
}
var t = TestEnum.test1
t = .test2
t = .test3
print(MemoryLayout.size(ofValue: t)) 
print(MemoryLayout.stride(ofValue: t)) 
print(MemoryLayout.alignment(ofValue: t)) 
print(UnsafeMutablePointer(&t))
---------------執行結果------------------
1
1
1
0x00007ffeefbff438
x/1xg 0x7ffeefbff438
0x7ffeefbff438: 0x0000000000000002 // 從這裡可以看出只需要一個位元組就能把這個列舉表達出來了
複製程式碼
enum TestEnum {
    case test1(Int, Int, Int)
    case test2(Int, Int)
    case test3(Bool)
    case test4
}
var t1 = TestEnum.test1(10, 11, 12)
var t2 = TestEnum.test3(true)
var t3 = TestEnum.test4

print(MemoryLayout.size(ofValue: t1))
print(MemoryLayout.stride(ofValue: t1))
print(MemoryLayout.alignment(ofValue: t1))

print(UnsafeMutablePointer(&t1))
print(UnsafeMutablePointer(&t2))
print(UnsafeMutablePointer(&t3))

---------------執行結果------------------
25
32
8
0x00007ffeefbff420
0x00007ffeefbff400
0x00007ffeefbff3e0
(lldb) x/12wg 0x00007ffeefbff3e0
0x7ffeefbff3e0: 0x0000000000000000 0x0000000000000000
0x7ffeefbff3f0: 0x0000000000000000 0x0000000000000003
0x7ffeefbff400: 0x0000000000000001 0x0000000000000000
0x7ffeefbff410: 0x0000000000000000 0x00007ffeefbff402
0x7ffeefbff420: 0x000000000000000a 0x000000000000000b
0x7ffeefbff430: 0x000000000000000c 0x0000000000000000
複製程式碼
enum TestEnum {
    case test1(Bool)
    case test2(Int, Bool)
}
var t1 = TestEnum.test1(true)
var t2 = TestEnum.test2(1, true)
var t3 = TestEnum.test1(false)
print(UnsafeMutablePointer(&t1))
print(UnsafeMutablePointer(&t2))
print(UnsafeMutablePointer(&t3))
print(MemoryLayout.size(ofValue: t1))
print(MemoryLayout.stride(ofValue: t1))
print(MemoryLayout.alignment(ofValue: t1))

---------------執行結果------------------
0x00007ffeefbff430
0x00007ffeefbff420
0x00007ffeefbff410
9
16
8
(lldb) x/8wg 0x00007ffeefbff400
0x7ffeefbff400: 0x0000000000000001 0x00007fff8afcb9e0
0x7ffeefbff410: 0x0000000000000000 0x00007ffeefbff400
0x7ffeefbff420: 0x0000000000000001 0x0000000000000081
0x7ffeefbff430: 0x0000000000000001 0x0000000000000000
複製程式碼
  • 列舉所需要的記憶體就是儲存關聯值所需要的位元組數(取每個位上面佔用最多的位元組,任何一個 case 的關連值都共用這幾個位元組)的和加上成員值(1個位元組)所需要的位元組數。
  • 有時候會將列舉的成員值跟其他型別的值關聯儲存在一起,會非常有用
  • 原始值(rawValue)不佔用列舉變數的記憶體
  • 特別注意:如果一個列舉裡面只有一個case,並且沒有關聯值,那麼它實際佔用的記憶體為0個位元組,系統會分配一個位元組,位元組對齊也是一個位元組(因為只要有就知道是他,所以不需要浪費額外的記憶體再去儲存了)

那麼是如何通過 rawValue 來獲取原始值的呢?

和儲存屬性一樣。

如何將 enum 中的關聯值取出來

  • 先去根據型別,找到成員值儲存在記憶體中的哪一位元組中,然後判斷是哪一個case,最後再將其他的記憶體中的值依次傳入case的引數中。

相關文章