函数/方法调用 参数传递规则总结:
- C函数调用:参数先后顺序传入x0, x1, x2…寄存器。
- OC方法调用:其本质是 objc_sendMsg C函数调用。参数依次为 self, sel, 参数0, 参数1… 即:x0=对象本身,x1=方法名, x2=参数0,x3=参数1…
- C++方法调用:obj->func(a,b,c,d) 等价于 func(obj, a,b,c,d),即:x0=对象本身,x1=参数0,x2=参数1…
- swift方法调用:obj.func(a, b, c) 等价于 func(a, b, c, self),即:x0=参数0, x1=参数1,x2=参数,最后是对象本身。
OC方法调用的参数传递规则:
首先来看一下测试代码,如下:
- (void)viewDidLoad
{
[self sayH1:1 h2:2 H3:3 h4:4 H5:5 h6:6 H7:7 h8:8 H9:9 h10:10];
}
- (void)sayH1:(NSInteger)h1 h2:(NSInteger)h2
H3:(NSInteger)h3 h4:(NSInteger)h4
H5:(NSInteger)h5 h6:(NSInteger)h6
H7:(NSInteger)h7 h8:(NSInteger)h8
H9:(NSInteger)h9 h10:(NSInteger)h10 {
int x1 = 1;
int x2 = 2;
int x3 = 3;
int x4 = 4;
int x5 = 5;
int x6 = 6;
int x7 = 7;
int x8 = 8;
NSLog(@"x * y * h10 = %ld");
}
复制代码
参数传递规则如下: self, SEL, 参数1,参数2,参数3…参数6;除开 self, sel最多传递6个参数,多余的函数参数存储在上一个堆栈中。然后就是局部变量1,局部变量2。
内存如下:
(lldb) x/30xg 0x000000016f209c20 (sp 栈顶寄存器)
0x16f209c20: 0x4094780000000000 0x0000000000000000
0x16f209c30: 0x4079e00000000000 0x0000000000000000
0x16f209c40: 0x0000000700000008 0x0000000500000006 局部变量:x7,x8,x5,x6
0x16f209c50: 0x0000000300000004 0x0000000100000002 局部变量:x3,x4,x1,x2
0x16f209c60: 0x0000000000000006 0x0000000000000005 (参数6,参数5)
0x16f209c70: 0x0000000000000004 0x0000000000000003 (参数4,参数3)
0x16f209c80: 0x0000000000000002 0x0000000000000001 (参数2,参数1)
0x16f209c90: 0x0000000100f5490e 0x0000000101910330 (SEL,self)
0x000000016f209ca0: fp 栈底寄存器
-----------------------------------------------------------------------------------
0x16f209ca0: 0x000000016f209ce0 0x0000000100c0c8d4
0x16f209cb0: 0x0000000000000007 0x0000000000000008 (参数7, 参数8)
0x16f209cc0: 0x0000000000000009 0x000000000000000a (参数9,参数10)
0x16f209cd0: 0x00000001edd8024b 0x0000000101910330
0x16f209ce0: 0x000000016f209d10 0x00000001b88dd550
复制代码
swift方法调用
override func viewDidLoad() {
super.viewDidLoad()
test(x1: 1, x2: 2, x3: 3, x4: 4, x5: 5, x6: 6, x7: 7, x8: 8, x9: 9, x10: 10)
}
func test(x1:Int, x2:Int, x3:Int, x4:Int, x5:Int, x6:Int, x7:Int, x8:Int, x9:Int, x10:Int) {
let a = 16
let b = 17
let c = 18
let d = 19
print("\(a+b+c+d)")
}
复制代码
其参数传递规则如下:参数1,参数2,…参数n, self.
内存如下:
完整的栈帧
————————————————————— 栈顶
0x16b4c5ae0: 0x0000000125e08870 0x0000000000000000
0x16b4c5af0: 0x000000016b4c5b40 0x152a63810c8704a4
0x16b4c5b00: 0x000000010c8683af 0x000000000000000e
0x16b4c5b10: 0x0000000000000008 0x000000000c868310
0x16b4c5b20: 0x0000000000000009 0x000000000000000a
0x16b4c5b30: 0x0000000000000004 0x0000000000000005
0x16b4c5b40: 0x0000000000000006 0x0000000000000007
0x16b4c5b50: 0x0000000000000008 0x0000000125e08870
0x16b4c5b60: 0x0000000000000003 0x0000000000000002
0x16b4c5b70: 0x0000000000000001 0x0000000125e08870 (self)
0x16b4c5b80: 0x000000000000000a 0x0000000000000009 (参数10,参数9)
0x16b4c5b90: 0x0000000000000008 0x0000000000000007 (参数8,参数7)
0x16b4c5ba0: 0x0000000000000006 0x0000000000000005 (参数6,参数5)
0x16b4c5bb0: 0x0000000000000004 0x0000000000000003 (参数4,参数3)
0x16b4c5bc0: 0x0000000000000002 0x0000000000000001 (参数2,参数1)
—————————————————————————————— 栈底
复制代码
OC对象内存模型:
typedef struct objc_object {
Class isa;
} *id;
复制代码
每个 Objective-C 对象都有相同的结构,如图:
不论是 普通的OC对象,还是类对象,元类对象,或者Block对象,第一个8字节都是isa.
swift对象内存模型:
class Human {
var age: Int?
var name: String?
var nicknames: [String] = [String]()
}
复制代码
swift中所有分配在堆上的东西都是一个HeapObject。我们看看HeapObject的定义:
/** 我们看到其实就两个变量,一个metadata,和一个InlineRefCounts */
struct HeapObject{
/// This is always a valid pointer to a metadata object.
HeapMetadataconst*metadata;
InlineRefCounts refCounts;
};
复制代码
例如 swfit Data对象的内存如下:
注意字节顺序:
(lldb) x/100xg 0x00000001703f0200
0x1703f0200: 0x46466751704a4159 0x6a744e4636516944
由于是以xg表示,因此每8个字节组成一个64位 16进制数字,例如:
0x46466751704a4159, 其实际表示的字节顺序为: 59,41,4a, 70, 51,67, 46, 46。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END