枚举变量的内存布局
-
查看内存布局的方法
- 得到变量的内存地址 Xcode -> Debug -> Debug Workflow -> View Memory -> 输入内存地址
- 在下边栏 右击 点击 view memory of ""
-
普通枚举
enum TestEnum {
case test1, test2, test3
}
// 0x00 ~ 0xFF 256个CASE 简单枚举只占用一个字节
var t = TestEnum.test1
print(Mems.ptr(ofVal: &t)) //此方法用于得到内存地址 0x0000000100006568 占用一个字节 显示为0
t = .test2 // 1
t = .test3 // 2
- 原始值枚举
enum TestEnum : Int{
case test1, test2, test3
}
// 0x00 ~ 0xFF 256个CASE 原始枚举只占用一个字节
var t = TestEnum.test1
print(Mems.ptr(ofVal: &t)) //此方法用于得到内存地址 0x0000000100006568 占用一个字节 显示为0
t = .test2 // 1
t = .test3 // 2
- 关联值枚举
enum TestEnum {
case test1(Int, Int, Int)
case test2(Int, Int)
case test3(Int)
case test4(Bool)
case test5
}
// 枚举如果有关联值 必然有 1个字节存储成员值, N个字节存储关联值(N取占用内存最大的关联值) 任何一个case的关联值都共用这个N个字节 如果只有一个成员 就不需要1个字节去存储成员值
// 小端模式: 高高低低 0x 00 00 00 00 00 00 00 01
var e = TestEnum.test1(1, 2, 3)
// 01 00 00 00 00 00 00 00 (1)
// 02 00 00 00 00 00 00 00 (2)
// 03 00 00 00 00 00 00 00 (3)
// 00 (这个字节用来存储成员值test1)
// 00 00 00 00 00 00 00
print(Mems.ptr(ofVal: &e))
e = .test2(4, 5)
// 04 00 00 00 00 00 00 00 (1)
// 05 00 00 00 00 00 00 00 (2)
// 00 00 00 00 00 00 00 00 (3)
// 01 (这个字节用来存储成员值test2)
// 00 00 00 00 00 00 00
e = .test3(6)
// 06 00 00 00 00 00 00 00 (1)
// 00 00 00 00 00 00 00 00 (2)
// 00 00 00 00 00 00 00 00 (3)
// 02 (这个字节用来存储成员值test3)
// 00 00 00 00 00 00 00
e = .test4(true)
// 01 00 00 00 00 00 00 00 (1)
// 00 00 00 00 00 00 00 00 (2)
// 00 00 00 00 00 00 00 00 (3)
// 03 (这个字节用来存储成员值test4)
// 00 00 00 00 00 00 00
e = .test5
// 00 00 00 00 00 00 00 00 (1)
// 00 00 00 00 00 00 00 00 (2)
// 00 00 00 00 00 00 00 00 (3)
// 04 (这个字节用来存储成员值test5)
// 00 00 00 00 00 00 00
- 只有一个成员的简单枚举
enum TestEnum {
case test
}
var t = TestEnum.test
// 根本没有占用内存
print(MemoryLayout<TestEnum>.size)// 0
print(MemoryLayout<TestEnum>.stride)// 1
print(MemoryLayout<TestEnum>.alignment)// 1
汇编分析枚举
在图示位置添加断点,得到下面汇编代码
// 下面是这句代码的汇编
var e = TestEnum.test1(10, 20, 30)
// rip 地址为 0x000000010000146f rip存储的是指令的地址,存储的是CPU要执行的下一条指令地址
//内存地址: rip + 0x50ce 即为 0x10000147a + 0x50ce = 0x100006548即为变量e的地址
// <+63> 表示前面的所有指令占用的字节数
0x10000146f <+63>: movq $0xa, 0x50ce(%rip);
// rax = 0x100006548
0x10000147a: leaq 0x50c7(%rip), %rax
0x100001481: movq $0x14, 0x50c4(%rip); //0x100006556
0x10000148c: movq $0x1e, 0x50c1(%rip); //0x100006564
//0x100006572 movb 将0一个字节 赋值给0x100006572这个地址, 这是枚举的成员值
0x100001497: movb $0x0, 0x50c2(%rip);