目录
值类型、引用类型的let
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寄存器 每次运行到相同的指令时 寄存器内存储的地址不一定相同
行者常至,为者常成!