JHHK

欢迎来到我的个人网站
行者常至 为者常成

4、枚举汇编分析

目录

查看int类型的内存分布

func memoryAnalyForInt() {
    //查看变量地址
    //view Memory of " "
    //Debug - Debug WorkFlow - View Memory
    var age:Int = 10
    
    print(MemoryLayout.size(ofValue: age))//8
    print(MemoryLayout.stride(ofValue: age))//8
    print(MemoryLayout.alignment(ofValue: age))//8
    
    print(Mems.ptr(ofVal: &age))//0x00007ffeefbff528
    print(Mems.memStr(ofVal: &age))//0x000000000000000a
}

查看枚举类型的内存分布(原始值的内存分布)

func memoryAnalyForEnum(){
    
    enum Season:String{
        case Spring,Summer,Autumn,Winner
    }
    
    print(MemoryLayout<Season>.size)        //1 实际占用
    print(MemoryLayout<Season>.stride)      //1 分配大小
    print(MemoryLayout<Season>.alignment)   //1 对齐参数

    
    //00 00 00 00 00 00 00 00
    var sum1 = Season.Spring
    print(sum1.rawValue)            //Spring
    print(Mems.ptr(ofVal: &sum1))   //0x00007ffeefbff468
    print(Mems.memStr(ofVal: &sum1))//0x00
    
    
    //01 00 00 00 00 00 00 00
    var sum2 = Season.Summer
    print(Mems.ptr(ofVal: &sum2))   //0x00007ffeefbff460
    print(Mems.memStr(ofVal: &sum2))//0x01
    
    
    //02 00 00 00 00 00 00 00
    var sum3 = Season.Autumn
    print(Mems.ptr(ofVal: &sum3))   //0x00007ffeefbff458
    print(Mems.memStr(ofVal: &sum3))//0x02
    
    
    //03 00 00 00 00 00 00 00
    var sum4 = Season.Winner
    print(Mems.ptr(ofVal: &sum4))   //0x00007ffeefbff450
    print(Mems.memStr(ofVal: &sum4))//0x03
}

查看枚举类型的内存分布(关联值的内存分布)

func memoryAnalyForEnum2(){
    //关联值的内存分布
    //1个字节存储成员值
    //N个字节存储关联值(N取占用内存最大的关联值)
    enum TestEnum {
        case test1(Int,Int,Int)//24
        case test2(Int,Int)//16
        case test3(Int)//8
        case test4(Bool)//1
        case test5//
    }
    
    print(MemoryLayout<TestEnum>.size)//25
    print(MemoryLayout<TestEnum>.stride)//32
    print(MemoryLayout<TestEnum>.alignment)//8
    

    var e = TestEnum.test1(1, 2, 3)
    print(Mems.ptr(ofVal: &e))
    print(Mems.memStr(ofVal: &e))
    //0x00007ffeefbff450
    //0x0000000000000001 0x0000000000000002 0x0000000000000003 0x0000000000000000
    
    
    e = .test2(4, 5)
    print(Mems.memStr(ofVal: &e))
    //0x0000000000000004 0x0000000000000005 0x0000000000000000 0x0000000000000001
    
    
    e = .test3(6)
    print(Mems.memStr(ofVal: &e))
    //0x0000000000000006 0x0000000000000000 0x0000000000000000 0x0000000000000002
    
    
    e = .test4(true)
    print(Mems.memStr(ofVal: &e))
    //0x0000000000000001 0x0000000000000000 0x0000000000000000 0x0000000000000003
    
    
    e = .test5
    print(Mems.memStr(ofVal: &e))
    //0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000004
}

特殊情况

func memoryAnalyForEnum3(){
    //因为枚举只有一个值 所以不需要区分 实际占用的内存空间为0
    enum Season2{
        case spring
    }
    print(MemoryLayout<Season2>.size)//0
    print(MemoryLayout<Season2>.stride)//1
    print(MemoryLayout<Season2>.alignment)//1
    
    var sum2 = Season2.spring
    print(Mems.ptr(ofVal: &sum2))//0x0000000000000001
    print(Mems.memStr(ofVal: &sum2))//空
    
    
    
    //因为只有一个枚举值 所以不需要额外的一个字节来区分枚举的成员值 所以只占用8个字节 而不是9个字节
    enum TestEnum2 {
        case test1(Int)
    }
    
    print(MemoryLayout<TestEnum2>.size)//8
    print(MemoryLayout<TestEnum2>.stride)//8
    print(MemoryLayout<TestEnum2>.alignment)//8
    var e2 = TestEnum2.test1(10)
    print(Mems.ptr(ofVal: &e2))//0x00007ffeefbff528
    print(Mems.memStr(ofVal: &e2))//0x000000000000000a
}

switch汇编分析

func memoryAnalyForSwich() {
    
    enum TestEnum3 {
        case test1(Int,Int,Int)
        case test2(Int,Int)
        case test3(Int)
        case test4(Bool)
        case test5
    }
    
    
    //0x100001e92 <+4914>:     movq   $0xa, 0x692b(%rip)
    //0x100001e9d <+4925>:     leaq   0x6924(%rip), %rdi
    //0x100001ea4 <+4932>:     movq   $0x14, 0x6921(%rip)
    //0x100001eaf <+4943>:     movq   $0x1e, 0x691e(%rip)
    //0x100001eba <+4954>:     movb   $0x0, 0x691f(%rip)
    
    //(lldb) register read rip
    //rip = 0x0000000100001e92  LCClientDemo-commond`main + 4914 at main.swift:163:1
    
    //0x100001e92 指令还未执行 此时寄存器 rip 存储的地址为 0x0000000100001e92
    //在该条指令将要执行时 rip 存储的值会变为下条指令的地址 0x100001e9d
    // 所以立即数$0xa  写入的内存地址为 0x100001e9d + 0x692b
    let e3 = TestEnum3.test1(10, 20, 30)
    
    switch e3 {
    case let .test1(v1, v2, v3):
        print("test1",v1,v2,v3)
        
    case let .test2(v1, v2):
        print("test2",v1,v2)
        
    case let .test3(v1):
        print("test3",v1)
        
    case let .test4(v1):
        print("test4",v1)
        
    case .test5:
        print("test5")
    }
}

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.