1. 枚举的基本用法
- 常见枚举的定义及使用
enum Direction{
case north
case south
case east
case west
}
/*等同于
enum Direction{
case north, south, east, west
}
*/
var dir = Direction.north
dir = Direction.south
dir = .east //因为已经确定了为Direction类型,也可以直接.east
2. 关联值(Associated Values)
- 有时会将枚举的成员值跟其他类型的关联存储在一起。会非常有用
enum Score {
case points(Int), grade(Character)
}
var score = Score.points(96)
//score = .grade("A")
switch score{
case var .points(i):
i = 95
print(i, "points")
case let .grade(i):
print(i, "grade")
}
enum Date {
case digit(year:Int, month:Int, day:Int)
case string(String)
}
var date = Date.digit(year: 2020, month: 07, day: 22)
switch date{
// case let Date.digit(y, m, d): let放在前面表示都为常量,必要时也可以var
case Date.digit(let y, let m, let d):
print(y,m,d)
case Date.string(let str):
print(str)
}
3. 原始值(Raw Values)
- 枚举成员可以使用相同类型的默认值预先关联,这个默认值叫做:原始值
enum PokerSuit : Character {
case spade = "♠"
case heart = "❤"
case diamond = "♦"
case club = "♣"
}
var suit = PokerSuit.heart
print(suit)//heart
print(suit.rawValue)//❤
- 隐式原始值,如果枚举的原始值类型是Int、 String,Swift会自动分配原始值
注意:这里的Int String只是表明原始值类型,并不是指枚举类型
enum Direction : String{
case north, south, east, west
}
/*等同于
enum Direction : String{
case north = "north"
case south = "south"
case east = "east"
case west = "west"
}
print(Direction.north)//north
print(Direction.north.rawValue)//north
enum Season : Int{
case spring, summer, autumn, winter//默认:0 1 2 3 ;
/*case spring = 1, summer, autumn = 4, winter //1,2,4,5 也可以单独指定*/
}
print(Season.summer)//summer
print(Season.summer.rawValue)//1
*/
4. 递归枚举了解
(Recursive Enumeration)
indirect enum ArithExpr {
case number(Int)
case sum(ArithExpr, ArithExpr)
case difference(ArithExpr, ArithExpr)
}
/*等同于
enum ArithExpr {
case number(Int)
indirect case sum(ArithExpr, ArithExpr)
indirect case difference(ArithExpr, ArithExpr)
} */
let five = ArithExpr.number(5)
let four = ArithExpr.number(4)
let two = ArithExpr.number(2)
let sum = ArithExpr.sum(five, four)
let diff = ArithExpr.difference(sum, two)
func calculate(_ expr:ArithExpr) -> Int {
switch expr {
case let .number(value):
return value
case let .sum(left , right):
return calculate(left) + calculate(right)
case let .difference(left, right):
return calculate(left) - calculate(right)
}
}
let res = calculate(diff) // 5 + 4 - 2
print(res) //7
5. 关联值 原始值内存分配上的区别:
关联值会把对应的值直接存储到枚举变量里面,会占用内存
原始值并不是存储到枚举变量里面的,它只占用一个字节
enum Password {//关联值
case num(Int, Int, Int ,Int)
case other
}
enum Season : Int{//原始值
case spring = 2, summer , autumn = 5, winter
}
let passwordSize = MemoryLayout.size//实际占用的内存
let passwordSize2 = MemoryLayout.stride//系统分配的内存
let passwordSize3 = MemoryLayout.alignment//内存对齐
let seasonSize = MemoryLayout.size//实际占用的内存
let seasonSize2 = MemoryLayout.stride//系统分配的内存
let seasonSize3 = MemoryLayout.alignment//内存对齐
print("PasswordMemorySize:",passwordSize,passwordSize2,passwordSize3)
print("SeasonMemorySize:",seasonSize,seasonSize2,seasonSize3)
/*PasswordMemorySize: 33 40 8
SeasonMemorySize: 1 1 1*/
内存分配:
enum testEnumNum1 {
case test1, test2, test3, test4
}
print("size1:",MemoryLayout.size)//实际占用的内存 1
print("stride1:",MemoryLayout.stride)//系统分配的内存 1
print("alignment1:",MemoryLayout.alignment)//内存对齐 1
var ten1 = testEnumNum1.test1
print(Mems.ptr(ofVal: &ten1))
ten1 = testEnumNum1.test2
ten1 = testEnumNum1.test3
ten1 = testEnumNum1.test4
print("============ 2 ===========")
enum testEnumNum2:Int {
case test1, test2, test3, test4
}
print("size2:",MemoryLayout.size)//实际占用的内存 1
print("stride2:",MemoryLayout.stride)//系统分配的内存 1
print("alignment2:",MemoryLayout.alignment)//内存对齐 1
/*
00 00 00 00 00 00 00 00
*/
var ten2 = testEnumNum2.test1
print(Mems.ptr(ofVal: &ten2))
/*
01 00 00 00 00 00 00 00
*/
ten2 = testEnumNum2.test2
/*
02 00 00 00 00 00 00 00
*/
ten2 = testEnumNum2.test3
ten2 = testEnumNum2.test4
print("============ 3 ===========")
/*
1个字节存储成员值
n个自己存储关联值(n取占用内存最大的关联值,任何一个case的关联值都公用这n个字节)
*/
enum testEnumNum3 {
case test1(Int)
case test2(Int,Int)
case test3(Int,Int,Int)
case test4(Bool)
case test5
}
print("size3:",MemoryLayout.size)//实际占用的内存 25
print("stride3:",MemoryLayout.stride)//系统分配的内存 32
print("alignment3:",MemoryLayout.alignment)//内存对齐 8
/*
01 00 00 00 00 00 00 00 //关联值
00 00 00 00 00 00 00 00 //关联值
00 00 00 00 00 00 00 00 //关联值
00 //成员值,第几个,从0开始
00 00 00 00 00 00 00
*/
var ten3 = testEnumNum3.test1(1)
print(Mems.ptr(ofVal: &ten3))
/*
02 00 00 00 00 00 00 00 //关联值
03 00 00 00 00 00 00 00 //关联值
00 00 00 00 00 00 00 00 //关联值
01 //成员值,第几个,从0开始
00 00 00 00 00 00 00
*/
ten3 = testEnumNum3.test2(2,3)
/*
02 00 00 00 00 00 00 00 //关联值
03 00 00 00 00 00 00 00 //关联值
04 00 00 00 00 00 00 00 //关联值
02 //成员值,第几个,从0开始
00 00 00 00 00 00 00
*/
ten3 = testEnumNum3.test3(2,3,4)
ten3 = testEnumNum3.test4(true)
ten3 = testEnumNum3.test5
6 lldb 常用指令
- 读取寄存器的值
register read/格式
register read/x
- 修改寄存器的值
register write 寄存器名称 数值
register write rax 0
- 读取内存中的值
x/数量-格式-字节大小 内存地址
x/3xw 0x0000010
- 修改内存中的值
memory write 内存地址 数值
memory write 0x000010 10
- 格式
x是16进制,f是浮点,d是十进制
- 字节大小
b -byte 1字节
h -half word 2字节
w -word 4字节
g -giant word 8字节
- po 表达式
po/x $rax
print 表达式
-
线程调试指令
thread step-over 、 next 、 n
单步运算,把子函数当做整体一步执行(源码级别)thread step-in 、 step 、s
单步运算,遇到子函数会进入函数(源码级别)thread step-inst-over 、 nexti 、ni
单步运算,把子函数当做整体一步执行(汇编级别)thread step-inst、 stepi 、si
单步运算,遇到子函数会进入函数(汇编级别)thread step-out 、finish
直接执行完单签函数的所有代码,返回上一个函数(遇到断点会卡主)