C程序的编译链接过程

程序由源文件编译得到可执行文件看起来好像是很简单的过程,windows的IDE环境下,点一下bulid就可以生成可执行文件,在Linux环境下,gcc编译器也提供了很多选项可以很方便的从源文件生成可执行文件。事实上程序的编译和链接是一个非常复杂的过程,IDE帮我们隐藏了大量的细节。下面我们以最经典的hello,world程序来分析一下,从源程序到生成可执行文件都发生了哪些事情。

//main.c文件内容
#include<stdio.h>
int main()
{
printf(“hello,world.\n”);
return 0;
}

##1. 预处理
预处理的主要作用有三个:

  1. 处理源文件代码中以”#”开头的那些代码,比如#include,#define等。将所有的宏定义全部展开。
  2. 处理条件编译
  3. 删除所有注释

通过gcc的-E选项来预处理main.c文件。
gcc –E main.c –o main.i

这里写图片描述

查看一下生成的main.i的文件内容,可以看到stdio.h文件内的内容已经全部被插入到文件当中了,同时所有的宏定义也被展开(main.i文件很长,截取的是一部分)。在文件的最后是我们main函数的代码。

#2. 编译
编译就是将预处理得到的*.i文件生成汇编代码文件(.s文件)。注意:通常所说的编译是指程序从源代码到生成可执行文件的全过程,在这里指的由.i文件生成*.s文件的过程。输入下面的命令来实现编译过程,得到main.s文件。
gcc –S main.i –o main.s
main.s文件全部内容如下:
这里写图片描述

#3. 汇编
汇编就是将汇编代码变成机器码。每一条汇编语句几乎都对应了一条机器码。所以这一步骤非常简单,根据汇编指令和机器指令对照表一对一翻译就OK。输入下面的指令实现这一过程。
gcc –c main.s –o main.o
此时,main.o文件已经生成,这个时候main.o已经是一个二进制文件,不能用cat查看,用hexdump来看一下main.o文件内容。
这里写图片描述

可以看到main.o文件全部都是数字。不过main.o文件还是不能执行,因为还没有把库连接进来。
#4. 链接
链接就是将库文件链接到程序,库文件分为两种,一种是静态库(也成为存档文件),一种是动态库(也称为共享库)。关于静态库和动态库,请参考上一篇博文。
使用以下指令完成链接过程
gcc main.s –o main.out
生成main.out可执行文件。

以上就是从源文件到可执行文件的全部过程。这是一个很简单的范例,在main.c文件中仅包含了标准头文件,没有包含自定义的头文件。下面介绍一个简单的例子。
首先准备三个文件

//main.c文件内容
#include<stdio.h>
#include "fun.h"
int main()
{
    printf("the answer is %d\n",calc(5,6));
    printf("hello,world.\n");
    return 0;   
}
//fun.h文件内容
#ifndef FUN_H
#define FUN_H
int calc(int a,int b);
#endif
//fun.c文件内容
#include"fun.h"
int calc(int a,int b)
{
    return a+b;
}

在main.c文件中包含了fun.h文件,并调用了fun.h中定义的calc函数,calc函数的实现在calc.c文件中。
#1.预处理、编译、汇编main.c文件
gcc -c main.c -o main.o
这里写图片描述
此时main.o文件是不能生成可执行文件的。
这里写图片描述
编译器提示undefined reference to `calc’,因为我们没有链接库文件。
#2.创建静态库文件
1.首先,编译fun.c得到fun.o目标文件
gcc -c fun.c
这里写图片描述
2.然后,创建静态库文件
ar crv libfun.a fun.o
这里写图片描述
3.在某些系统中,还要为静态库生成一个内容表
ranlib libfun.a
4.库文件创建完成后,就可以链接了。
#3.程序链接静态库文件
前面已经生成了main.o文和libfun.a文件,现在我们链接一下,生成可执行文件。
gcc main.o -o main.out -L. -l fun
注意一下这条语句的规则,-L表示指定库文件目录,”.”表示当前文件夹,这里也可以写出目录完整路径。-l fun表示指定库文件名,库文件的完整名是libfun.a,前面的lib和后缀.a均省略。
这里写图片描述
可见,main.out文件已经生成,可以执行
这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值