编译时和运行时、OC中对象的动态编译机制

时间:2023-03-09 00:56:25
编译时和运行时、OC中对象的动态编译机制

编译时

编译时顾名思义就是正在编译的时候.那啥叫编译呢?就是编译器帮你把源代码翻译成机器能识别的代码.(当然只是一般意义上这么说,实际上可能只是翻译成某个中间状态的语言.比如Java只有JVM识别的字节码,C#中只有CLR能识别的MSIL.另外还有啥链接器.汇编器.为了了便于理解我们可以统称为编译器)

编译时就是简单的作一些翻译工作,比如检查老兄你有没有粗心写错啥关键字了啊.有啥词法分析,语法分析之类的过程.就像个老师检查学生的作文中有没有错别字和病句一样.如果发现啥错误编译器就告诉你.如果你用微软的VS的话,点下build.那就开始编译,如果下面有errors或者warning信息,那都是编译器检查出来的.所谓这时的错误就叫编译时错误,这个过程中做的啥类型检查也就叫编译时类型检查,或静态类型检查(所谓静态嘛就是没把真把代码放内存中运行起来,而只是把代码当作文本来扫描下).所以有时一些人说编译时还分配内存啥的肯定是错误的说法.

运行时

所谓运行时就是代码跑起来了.被装载到内存中去了.(你的代码保存在磁盘上没装入内存之前是个死家伙.只有跑到内存中才变成活的).而运行时类型检查就与前面讲的编译时类型检查(或者静态类型检查)不一样.不是简单的扫描代码.而是在内存中做些操作,做些判断.

1、为什么OC不能sizeof一个对象的大小?和类结构相近的结构体却可以 
因为oc的动态继承编译机制,动态继承机制,就是说在编译的时候不能确定父类的大小,只有在运行时才能确定父类大小,

sizeo是在栈中操作的,编译的时候就会计算出来sizeof的值

而栈中不知道对象的父类大小,所以不能使使用sizeof计算出对象的大小
2、为什么OC不能将对象声明到静态空间,如栈中,和类相近的结构体却可以

栈是在编译完成后产生的,编译的结果是二进制机器文件,即汇编栈已经产生,所以栈内不能放类的对象,因为产生栈的时候不知道父类的大小

栈是由汇编代码指令描述的
为什么结构体可以直接寄计算sizeof,也能直接声明到静态空间呢?
为什么结构体不管定义在栈中或堆中都能直接sizeof?因为定义到堆中的时候已经知道了结构体的大小,因为结构体对于调用它的代码产生的栈而言是暴露的。
是因为结构体定义的头文件直接把结构体的属性暴露给了栈,所以可以直接声明到静态空间

总之一句话,父类的详细情况对于调用其子类的栈来说是封闭的,而结构体相对于调用它的栈来说是暴露的。

OC中的动态继承编译机制是在编译的时候不把父类详细情况暴露给调用子类的栈,而是在运行的时候才把父类的详细情况暴露给调用子类的栈