变量、运算符、控制结构
变量和运算符没什么好说的,非常基础的东西,接触过代码的都知道,不多说了,需要注意的可能就是变量命名规则,不同的数据类型占用的内存空间情况以及变量的作用空间(全局和局部)和在不同的作用空间中变量的初始化情况,运算符需要注意的就是优先级了,就像平常的算术运算* / 高于+ -一样。
局部变量默认初始值不确定,因为为局部变量分配的内存可能曾经被使用过并且没有被特意清除,所以可能包含的是之前使用的内容。而全局变量会初始化为0。
局部变量在运行时栈中,而全局变量在全局数据段中,注意,局部变量被修饰为static的情况下也被放入全局数据段,只是其访问规则是内部而不是全局。(运行时栈和全局数据段接下来说)
之前大概说了下编译过程,现在详细的说一说编译器的处理。
编译器在完成翻译工作的时候,需要借助两个机制:符号表和内存的系统分配。
编译器在编译过程中,将与变量相关的信息记录在符号表中,并根据变量的特性分配内存。
符号表:
和汇编器一样,编译器每扫描到一个变量声明语句,就在符号表中为该变量创建一个新表项。表项结构包括名字,类型,已分配的内存地址,变量声明域或作用域等信息。
例如下图
变量的内存分配:
存放变量的内存空间有两种区段:全局数据段(global data section)和运行时栈(run-time stack)。
全局数据段是内存存放全局变量的区段,即所有静态类变量所在的地方,运行时栈则是局部变量所在的地方。
符号表中的偏移字段,提供有关变量在内存中更为精确的位置信息,它代表的是变量存储地址距离内存段基地址的偏移量
看上图就明白了。
在编译器生成机器代码中,R4是一个专用寄存器,它存放全局数据段的基地址。所以R4又称为全局指针
全局变量地址非常简单,直接 LDR R3,R4,#offset 即可。
而局部变量就变得非常复杂了:
一个函数的所有局部比变量存放在一个称为“活动记录”或者“堆栈帧”的内存模板中,活动记录就是一段连续的内存空间,它包含了当前函数中的所有局部变量,调用函数时,函数活动记录的最大地址存放在R5寄存器中,因此R5又称为“帧指针”,像上图的偏移量所示,变量的偏移是负值,即R5指向入口地址,变量的地址从大到小分配。
R5在函数调用过程中,会随着活动记录的压入和弹出而修改,压入时,R5指向当前栈顶(记录的基地址),弹出时指向调用者活动记录所在位置。
而整个过程中寄存器R6始终指向运行时栈的顶部,因此称R6为“栈指针”。
存储类型:
静态和自动
静态变量的内容在两次启动之间不会改变,而自动变量在代码块结束后就丢弃。全局变量和加了static修饰符的局部变量是静态的,普通局部变量是自动的。
控制结构:
顺序结构、 条件结构、循环结构。
顺序结构就是按一个顺序往下执行指令。
条件结构 if-else switch
循环 for while do-while (循环会用到break(跳出循环) continue(跳过该次循环))