# 11、理解objc\_msgSend的作用

可以看这篇： [iOS\_Objective-C 消息发送（消息查找 及 消息转发）过程](https://blog.csdn.net/Margaret_MO/article/details/109222260)中的 一二、OC中的消息和消息查找

​ 上面文章讲述的自描述了部分消息的调用过程，其他“边界情况”（edge case）则需要交由Objective-C运行环境中的另一些函数来处理：

* `objc_msgSend_stret`：消息返回结构体时调用此方法。（当CPU的寄存器能容纳的心返回值类型时，否则用的是另一个函数）
* `objc_msgSend_fpret`：消息返回浮点数时调用此方法。需要对“浮点数寄存器”（floating-point register）做特殊处理。
* `objc_msgSendSuper`：消息是给超类发的。如：`[super someMethod:parameter]`。也有另外两个与`objc_msgSend_stret`和`objc_msgSend_fpret`等效的函数，用于处理发给`super`的相应消息。

还有一个概念需要理解一下：“**尾调用优化**”（tail-call optimization）技术：

​ 如果**某函数的最后一项操作是调用另外一个函数且不会返回值另作他用时**，那么就可以运用“尾调用优化”技术。编译器会生成调转至另一函数所需的指令码，且不会向调用堆栈中推入新的“栈帧”（frame stack）。（这项优化对`objc_msgSend`非常关键，若不做优化的话，每次调用OC方法前，都需要为`objc_msgSend`函数准备“**栈帧**”(可以在“栈踪迹”`stack trace`中看到)，还会过早地发生“栈溢出”（stack overflow）现象）。

​ 明白这一点，就能理解为何在在调试的时候，栈“回溯”（backtrace）信息中总是出现`objc_msgSend`了。

要点：

* 消息由接收者、选择子、参数构成。给某对象“发送消息”（invoke a message）也就相当于在该对象上“调用方法”（call a method）。
* 发给某对象的全母消息都要用“动态消息派发系统”（dynamic message dispatch system）来处理，该系统会查出对应的方法，并执行其代码。
