Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1737656
  • 博文数量: 358
  • 博客积分: 2180
  • 博客等级: 大尉
  • 技术积分: 1810
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-17 13:47
文章分类

全部博文(358)

文章存档

2016年(17)

2015年(55)

2014年(9)

2013年(67)

2012年(181)

2011年(29)

分类:

2012-06-25 14:39:00

原文地址:C/C++程序编译过程 作者:

当我们进行编译的时候,要使用一系列的工具,我们称之为工具链,其中包括:
预处理器cpp
编译器gcc/g++
汇编器as
链接器ld

一个C/C++程序编译过程包括下面几个阶段:

预处理    预处理器cpp将对源文件中的宏进行展开。
编译     gcc将c文件编译成汇编文件。
汇编     汇编器as将汇编文件编译成机器码。
链接     链接器ld将目标文件和外部符号进行连接,得到一个可执行二进制文件。

下面以一个很简单的 hello.c 来探讨这个过程
```
#include
#define BUFSIZE 1024

int main(int argc, char *argv[])
{
    char hello[BUFSIZE] = "Hello my friend!";
    printf("%s\n", hello);
    return 0;
}
```

### 预处理(预处理器 cpp)

[butbueatiful@xt myhello]$ gcc -E hello.c -o hello.i

[butbueatiful@xt myhello]$ cpp hello.c -o hello.i

我们用vi打开 hello.i 可以看到有如下内容:
......
int main(int argc, char *argv[])
{
    char hello[1024] = "Hello my friend!";
    printf("%s\n", hello);
    return 0;
}
我们可以看到,文件中宏定义 BUFSIZE 出现的位置被 1024 替换掉了,其它的内容保持不变。

### 编译器将 .i 文件编译成汇编文件

[butbueatiful@xt myhello]$ gcc -S hello.i # 得到汇编文件hello.s

### 汇编器将汇编文件编译成机器码(汇编器 as)
[butbueatiful@xt myhello]$ gcc -c hello.s -o hello.o

[butbueatiful@xt myhello]$ as hello.s -o hello.o

hello.o中为目标机器上的二进制文件

用 nm 查看文件中的符号:
[butbueatiful@xt myhello]$ nm -a hello.o
00000000 b .bss
00000000 n .comment
00000000 d .data
00000000 n .note.GNU-stack
00000000 t .text
00000000 a hello.c
00000000 T main
U puts
既然已经是二进制目标文件了,能不能执行呢?
[butbueatiful@xt myhello]$ chmod +x hello.o
[butbueatiful@xt myhello]$ ./hello.o
-bash: ./hello.o: cannot execute binary file
其实这时 puts 前面的 U 表示这个符号的地址还没有定下来,T表示这个符号属于代码段。ld连接的时候会为这些带U的符号确定地址。

### 链接(链接器 ld)
链接需要指定库的位置。通常程序中会有很多的外部符号,因此需要指定的位置就会很多。
不过,我们只需要调用 gcc 即可,ld会自己去找这些库的位置。
[butbueatiful@xt myhello]$ gcc hello.o -o hello # 得到可执行文件hello

阅读(1191) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~