枚举的内存布局

枚举变量的内存布局

  • 查看内存布局的方法

    • 得到变量的内存地址 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); 
 
上一篇:2021/7/23 在不断努力下总算出了一个结果


下一篇:Java异常