JHHK

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

5_2、结构体和类(二)

目录

值类型、引用类型的let

img

func letAnaly() {
    //1、let 分析(修饰值类型)
    struct Point{
        var x:Int
        var y:Int
    }
    
    let p = Point(x:10,y:20)
    print(MemoryLayout.size(ofValue: p))
    //常量p 内存内存储的是值类型 并且常量p所在的内存不允许更改 p.x p.y 对应的是p的前8字节和后8字节所以:
    //p = Point(x:11,y:21)//Cannot assign to value: 'p' is a 'let' constant
    //p.x = 21//Cannot assign to value: 'p' is a 'let' constant
    //p.y = 22//Cannot assign to value: 'p' is a 'let' constant
    
    
    
    //2、let 分析(修饰引用类型)
    class Size{
        var weight:Int
        var height:Int
        init(weight:Int,height:Int) {
            self.weight = weight
            self.height = height
        }
    }
    
    let c = Size(weight:80,height:180)
    //c是常量 不允许修改 c内存储的是指针类型
    //c = Size(weight: 81, height: 181)//Cannot assign to value: 'c' is a 'let' constant
    //c.weight c.height 修改的是c内存储的指针对应的内存空间 是 var 变量 可以修改
    c.weight = 81
    c.height = 181
}

结构体、类、枚举内部都可以定义方法

func defineFunc(){
    
    //1.结构体内定义方法
    do{
        struct Point {
            var x:Int
            var y:Int
            func show (){
                print("x = ",x, "y = ",y)
            }
        }
        
        let p = Point(x: 10, y: 20)
        p.show()
    }
    
    //2.类内定义方法
    do{
        class Size {
            var width:Int
            var height:Int
            init(width:Int,height:Int) {
                self.width = width
                self.height = height
            }
            func show(){
                print("width = ",width,"height = ",height)
            }
        }
        
        let s = Size(width: 10, height: 20)
        s.show()
    }
    
    //3.枚举内定义方法
    do{
        enum Season:String {
            case Spring, Summer, Autum, Winter
            func show(){
                print("rawValue is \(rawValue)")
            }
        }
        
        let s = Season.Spring
        s.show()
    }
}

嵌套类型分析

func nestTest() {
    struct Point{
        var x:Int
        var y:Int
        enum Season {
            case spring,summer,autmun,winer
        }
    }
    var p = Point(x:10,y:20)
    print(Mems.size(ofVal: &p))//16
    print(Mems.ptr(ofVal: &p))//0x00007ffeefbff520
    print(Mems.memStr(ofVal: &p))//0x000000000000000a 0x0000000000000014
    
    var s = Point.Season.summer
    s = .winer;
    print(Mems.size(ofVal: &s))//1
    print(Mems.ptr(ofVal: &s))//0x00007ffeefbff518
    print(Mems.memStr(ofVal: &s))//0x03
    
    /**
     enum 并不占用结构体的内存空间
     */
}

内存段分析

一、内存段分析

var str:String = "hello world"
func segmentAnaly(){
    //断点查看下 segmentAnaly的函数地址为:0x100008eb0
    
    
    class Size{
        var width:Int = 80
        var Height:Int = 180
        func show() {
            //在此断点查看下show方法的地址为:0x10000a170
            
            print(width,Height)
        }
    }
    
    var s = Size()
    s.show()
    
    print("数据段(全局变量)",Mems.ptr(ofVal: &str))
    print("堆空间(malloc)",Mems.ptr(ofRef: s))
    print("栈空间(局部变量)",Mems.ptr(ofVal: &s))
    
    /**
     内存地址从上往下依次变大:
     代码段(全局函数)  0x000100008eb0 //segmentAnaly的函数地址为
     代码段(嵌套函数)  0x00010000a170 //show方法的地址为
     数据段(全局变量)  0x000100011ef0
     堆空间(malloc) 0x00010200b160
     栈空间(局部变量)  0x7ffeefbff520
     
     从一个侧面证明 嵌套的函数位于代码段
     */
}

二、其它方法

func otherTest(){
    //在堆空间 申请内存 申请的内存是 16的倍数
    let s = malloc(16)
    
    //查看引用类型指向的堆空间的内存大小 如果size存储的是栈空间的地址则返回0
    let size = malloc_size(s)
    print("size",size)//size 16
    
    
    //申请的内存是 16的倍数
    let s2 = malloc(17)
    let size2 = malloc_size(s2)
    print("size2",size2)//size2 32
    
    
    //查看对象占用的空间大小
    class Size{
        var height = 10
        var weight = 20
    }
    let s3 = Size()
    let size3 = malloc_size(Mems.ptr(ofRef: s3))
    print("size3",size3)//size3 32
}

1、全局变量:数据段 程序启动后分配内存空间 整个过程地址不会发生改变

2、局部变量:函数调用时分配内存空间 调用结束空间回收

3、rip寄存器内放置的地址 是下调指令的地址 程序载入内存后指令地址不会发生改变 所以每次执行程序 执行到一条指令时 rip存储的地址都会是那个地址 不管程序执行多少次

4、rbp寄存器 每次运行到相同的指令时 寄存器内存储的地址不一定相同


行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.