static部分
static分两种情况,修饰局部变量和全局变量。
- 局部变量是存储在栈区的,它的⽣命周期是整个代码块,作⽤域
也是整个代码块,⼀旦出了这个代码块,存储局部变量的这个栈
内存就会被回收,局部变量也就被销毁了。
- ⽤static修饰局部变量时,这个静态局部变量和全局变量、静态全局变量⼀样,是存储在静态存储区。存储在静态存储区,所以这块内存直到程序结束才会销毁。但是它只在声明它的代码块可 见,所以其作⽤域还是声明它的代码块。
static修饰全局变量
- 当全局变量没有使⽤static修饰符时,其存储在静态存储区,直到程序结束才销毁。也就是其作⽤域是整个源程序。我们可以使⽤ extern关键字来引⽤这个全局变量。
- 当全局变量使⽤static修饰时,其⽣命周期没有变,依旧是在程序结束时才销毁。但是其作⽤只限于声明它的这个⽂件,使⽤extern关键词引⽤会报错。
为什么static修饰的变量只能在当前⽂件使⽤?
static修饰全局变量后,该变量符号在符号表中的 Bind 属性变为local ,对于符号解析原则,当遇到了⼀个local符合⽴即解析,并 不会继续再去后续的其他源⽂件中对相应的同名全局符号进⾏解 析绑定。 (代码段?数据段?)
所以经 static 修饰后的全局变量在本⽂件的链接期时,当这些全局符号被链接的时候会被⽴刻绑定到⽂件中相应的符号。当其他 源⽂件在链接的时候同样看到local属性的全局符号并不会对其绑 定。所以经由 static 修饰后,全局变量只在当前⽂件内有效,不 会被链接到其它⽂件中。
dumplicate symbols 、Undefined symbols等错误提⽰都是链接器 在链接过程中发现的问题。
编译时链接器做了什么?
1. Mach-O ⽂件⾥⾯到有什么?
主要就是代码和数据:代码是函数的定义;数据是全局变量的定 义,包括全局变量的初始值。不管是代码还是数据,它们的实例 都需要由符号将其关联起来。
2. 链接器将多个Mach-O⽂件合并成⼀个
⼀个项⽬⾥⼀定会有多个⽂件,项⽬中⽂件之间的变量和接⼜函 数都是相互依赖的,所以这时我们就需要通过链接器将项⽬中⽣ 成的多个 Mach-O ⽂件的符号和地址绑定起来。
没有这个绑定过程的话,单个⽂件⽣成的 Mach-O ⽂件是⽆法正常运⾏起来的。因为,如果运⾏时碰到调⽤在其他⽂件中实现的函数的情况时,就会找不到这个调⽤函数的地址,从⽽⽆法继续
执⾏。链接器在链接多个⽬标⽂件的过程中,会创建⼀个符号表,⽤于记录所有已定义的和所有未定义的符号。链接时如果出现相同符号,就会出现“ld: dumplicate symbols”的编译错误信息;
如果在其他⽬标⽂件⾥没有找到符号,就会提⽰“Undefined symbols”的编译错误信息。
3. 链接器对代码主要做了哪⼏件事⼉?
- 去项⽬⽂件⾥查找⽬标代码⽂件⾥没有定义的变量。
- 扫描项⽬中的不同⽂件,将所有符号定义和引⽤地址收集起
来,并放到全局符号表中。 - 计算合并后长度及位置,⽣成同类型的段进⾏合并,建⽴绑
定。 - 对项⽬中不同⽂件⾥的变量进⾏地址重定位。
总结:
static修饰局部变量:将局部变量的本来分配在栈区改为分配
在静态存储区,也就改变了局部变量的⽣命周期。
static修饰全局变量:全局变量本来是在整个源程序的所有⽂
件都可见,static修饰后,改为只在声明的那个⽂件可见,即
修改了其作⽤域。
const部分
warning 解释:指针变量赋值时,赋值语句左边的指针所指向的
类型必须具有赋值语句右边的类型所拥有的全部修饰符,才能正
常通过编译,否则就会舍弃右边变量多余的修饰符。