-
编译器的编译顺序:编译器从上到下顺序扫描程序。
-
sizeof() 编译时计算出来 ++运行时才进行
-
当进行模板处理时,其传入的实例,其实在编译器编译时会进行实参与形参结合的类型推演,后生成typedef 来改写程序。
-
对于自己设计的类型,如struct和class,编译器识别其从 struct开始到 ; 结束
类和结构体没有数据成员时,sizeof其大小为1 -
编译器对类的解析:
-
先扫描数据成员的属性 (与处于类的位置无关)
-
然后扫描成员函数的声明(不管函数定义),记录每一个成员函数(返回类型,函数名,参数列表)和访问属性
-
扫描成员函数的定义与声明是否对应,然后对每一个成员函数进行改写,参数增加了 (类名 * const this指针),然后开始扫描函数体,如果存在数据成员,则进行改写,最后在main里对对象调动成员函数语句进行改写。
编译器很难理解内存引用模式和过程调用的影响,所以不会去直接优化值传递。
返回值类型即函数返回时赋值,作为右值时,需要运算符两边类型相同,所以需要左值也是const * ,而返回过程eax(针对整形的)保存的只是其值,不关心其类型(char int long),其类型,且该值成为了右值 eax 就是这个临时量 a=fun () mov a的内存,eax
如char int 比较 先写入寄存器,而写入寄存器之前,其类型就被转换了,即这里发生了隐式转换。而这种转换是在编译阶段,编译器器就会检测出来,然后进行改写,相当于添加了强制转换了,然后在运行时,才进行写入寄存器,使得能正常的比较。所以返回值类型是在编译时就会确定下来的,即eax只管传值,而编译器早就每个地方都写入了类型。
student *s = (student *)malloc(sizeof(*s));//正确,
该设计sizeof是在编译时进行类型确认,所以在编译时是将计算了*s的类型,而类型确定是在编译的语义分析过程,而不是在运行时计算
6.词法分析,将扫描的程序一个一个的写入词法分析器里,拆分成一个个记号(这些记号是由贪心算法组合成的),这些记号有标识符,运算符,和特殊符号等,标识符变成了符号(汇编的时候将标识符记号放在符号表)。
7.语法分析,将词法分析处理好的符号和运算符送入到语法分析器里,构成语法树,确定语句的运算符的含义和优先级,但不管其语句的语义是否正确,如两个指针相乘等
8.(静态)语义分析,确定语句是否有效,进行类型的确定(类型转换)。
-
汇编 收集符号,形成符号表,将程序运行时没有用到的一些声明剔除(优化)。
-
管理着寄存器的缓存。
C++编译器对于函数调用
- 静态绑定 call 函数地址
- 动态绑定
- 通过指针调用
- 指针符合up-cast
- 虚函数