CSAPP基本版第七章学习日志(一):关于.o文件的生成以及初识链接

由前几章的学习我们已知程序的生命周期是从一个高级C语言程序开始的,在Unix系统上,GCC编译器驱动程序读取源程序文件(即.c文件),并把它翻译成一个可执行目标文件。例如从hello.c文件得到hello目标文件的过程为:
编译系统(图源深入理解计算机系统)
在这四个阶段中,预处理、编译和汇编针对一个模块(即一个.c文件)处理,得到相应的可重定位目标文件(一个.o文件),而链接就是将多个可重定位目标文件合并成可执行目标文件的过程。
如以下模块(.c文件):
static-local.c代码内容:

static int x = 15;

int f() {
    static int x = 17;
    return x++;
}

int g() {
    static int x = 19;
    return x += 14;
}

int h() {
    return x += 27;
}

通过读代码,可以知道static-local.c文件定义了一个静态全局变量x和3个函数,其中f和g函数在里面又定义了静态局部变量x,并且三个函数的返回值都是让x加上某值。由于该模块没有主函数main,因此在gcc -o static-local static-local.c指令时会报错:
运行结果
因此这个模块因缺少main而无法生成可执行目标文件,但它可以完成前三个阶段生成相应的可重定位目标文件,我们通过在命令行输入gcc -Wall -Og -c static-local.c(-c表示只编译,不链接)可得到这个模块的可重定位目标文件(static-local.o)
gcc -Wall -Og -c static-local.c
其中,

  • -Wall表示允许发出gcc提供的所有有用的报警信息
  • -Og表示启用全局优化
  • -c表示只编译,不链接。

通过此条命令即可在static-local.c文件所在目录下找到相应的可重定位目标文件static-local.o。
运行结果
关于链接知识:
每个可重定位目标文件模块m都有一个符号表,它包含m定义和引用的符号的信息(符号即一个函数、一个全局变量或一个静态变量)其中有三种不同的符号:

  • 由模块m定义并能被其他模块引用的全局符号,即非静态的C函数和全局变量。
  • 由其他模块定义并被模块m引用的全局符号,被称为外部符号,即其他模块定义的非静态的C函数和全局变量。
  • 只被模块m定义和引用的局部符号,即带static属性的C函数和全局变量。

注意,定义为带有C static属性的本地过程变量是不在栈中管理的。编译器在符号表中创建一个有唯一名字的本地链接器符号。例如同一模块的f和g函数各自定义了一个静态局部变量x,在这种情况下,编译器向汇编器输出两个不同名字的局部连接器符号。比如,它可以用x.1表示f中的定义,而用x.2表示g中的定义,这也是静态变量比起当发生变量名相同时会替代变量的全局变量的优势。

补充:因为static的定义,如果在该模块定义主函数main来分别调用这3个函数,调用f和g时分别是令x.1和x.2变化,而不会影响x,只有调用h时是令静态全局变量x的值发生变化。

关于static更多信息可参考:static在C语言中主要是两种用法C语言中static的作用及C语言中使用静态函数有何好处

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值