CSAPP第七章
7.1
1.函数后没跟函数体则为声明,跟了则为定义
下列情况仅为声明
1: 仅仅提供函数原型:void display();
2: extern int a;
3: class A;
4: typedef 声明;
5: 在类中定义的静态数据成员的声明
class A{
public:
static int a; //声明
};
局部变量 仅由模块m定义和引用的本地符号
e.g.在模块中定义的带static的C函数和全局变量
注意函数中的局部变量如temp存在栈中,不存在symtab中
2.不在此处定义,要声明全局变量时,要加extern关键字
7.4
1..data 已初始化的全局和静态变量
.bss未初始化的静态变量和已被初始化为0的全局或静态变量
在目标文件中不占据实际空间
COMMON未初始化的全局变量
.text已编译程序的机器代码
2.判断某个文件中的符号是否是该模块的.symtabl节中有的符号表条目的方法
如果有,还需要判断其符号类型,所处在的节,还有定义的模块
首先先看这个符号在文件中是否是某个函数里面的非静态局部变量,如果是,那么这个符号就不在这个模块的.symtabl条目
接下来判断符号类型,
如果是extern的全局变量,那么他是外部的(extern)。
如果是非静态的函数名,那么它是全局的(global)。
如果是static的静态变量,那么它是本地的(local)。
如果是static的静态函数名,那么它是本地的(local)。
其他的正常的变量都是全局的(global)
接着判断定义模块
根据符号类型就可以判断了,
外部(extern)的的就不是本模块定义的
剩下的本地的(local)和全局的(global)都是本模块定义的
最后判断它所在模块中所处的节
如果它是函数名,就在.text节中
如果它是初始化过的变量,就在.data节中
如果它是未初始化的变量,就在.bss节中
特例
(如果static int count=0这个count不管是全局还是局部,在ubuntu里面测试了之后发现它都在.bss段中)
————————————————
转自 原文链接:https://blog.csdn.net/qq6304403348/article/details/73056532
练习题7.3
.o目标文件
.a静态库(存档文件)
解析静态库的过程是按照命令行标识的文件顺序从左到右解析,如果输入文件是一个目标文件(.o),那么将文件添加到集合E(合并成执行文件);如果f是一个存档文件(.a),那么就尝试解析集合U(未解析的符号),能够解析的话就将其加载到集合E中去;重复这样的过程直到都解析完毕。 目标文件将整个添加到E,且不像存档文件一样遍历。链接器维护一个可重定位目标文件的集合E(这个集合中的文件就是确定的最后合并成可执行文件的模块文件),
一个未解析的符合(即引用了但尚未定义的符号)集合U,以及一个已解析(前面已经定义但没有被引用)集合D。
对于命令行上的每个文件 f ,链接器会判断 f 是一个目标文件还是存档文件。
1.判断输入文件类型
如果是目标文件
链接器将会把这个文件添加到集合E,并根据符号引用情况修改集合U和D的状态。然后处理下一个文件。
如果是存档文件
链接器将尝试匹配集合U中未解析的符号和存档文件成员定义的符号,如果存档文件的成员m定义了一个符号来解析U中的一个引用,
那么久将m加入到集合E中,然后修改U和D的状态。对存档文件中的每个成员都重复这个过程,直到U和D不再发生变化,然后简单地丢弃
不包含在集合E中的成员目标文件。然后链接器继续处理下一个文件。
2.判断集合U是否为空
如果链接器扫描完命令行上的所以文件后,集合U仍不为空,则说明引用了未定义的符号,则链接器将会报错并终止程序。
如果链接器扫描完命令行上的所以文件后,集合U仍为空,则将合并和重定位E中的目标文件,并输出可执行文件。
注意命令行上的库和目标文件的顺序
一般将库放在命令行的结尾
1.如果库之间是相互独立的,则可以以任意的顺序放在命令行的结尾处。
2.如果库之间是相互依赖的关系,则必须对他们排序,使得对于每个被存档文件的成员外部引用的符号s,在命令行中至少有一个s的定义是在对s的引用之后的。
例如,a和b表示当前目录中的目标模块或者静态库,而a->b表示a依赖于b,也就是说b定义了一个被a引用的符号。
p.o->libx.a->liby.a且liby.a->libx.a->p.o
可得最小命令行 gcc p.o libx.a liby.a libx.a
注意不要写成 gcc p.o libx.a liby.a libx.a p.o //要注意区分存档文件和目标文件,目标文件将整个添加到E,并不会像存档文件一样遍历。