程序员的自我修养——编译和链接

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sunxianghuang/article/details/78827257

2.1被隐藏了的过程

Hello World程序hello.c

#include<stdio.h>

int main(){
    printf("Hello World!");
    return 0;
}

在Linux下,使用GCC编译和执行Hello World程序时,只需使用最简单的命令。

$ gcc hello hello.c
$ ./hello
Hello World

事实上,上述过程可以分解为4个步骤,分别是预处理(Prepressing)、编译(Compilation)、汇编(Assembly)和链接(Linking)。
GCC编译过程分解

2.1.1 预编译

首先,源代码文件hello.c和相关头文件stdio.h等被预编译器cpp预编译成hello.i文件。

$ gcc -E hello.c -o hello.i
或者
$ cpp hello.c>hello.i

预编译过程主要处理那些源文件中以“#”开始的预编译指令。
主要处理规则如下:

  • 将所有的“#define”删除,并且展开所有的宏定义。
  • 处理所有条件预编译指令,比如“#if”,”ifdef”,”#elif”,“#else”,”endif”。
  • 递归处理“#include”预编译指令,将被包含的文件插入到该预编译指令的位置。
  • 删除所有的注释“//”和“/**/”。
  • and so on

    2.1.2 编译

    编译过程就是把预处理后的文件进行一些列词法分析、语法分析和语义分析,然后优化生成相应的汇编代码文件。

$ gcc -S hello.i -o hello.s
或者
$ ccl hello.c

hello.s文件
关于GCC命令:对于C语言来说,预编译和编译的程序是ccl,对于C++来说,对应程序是cclplus;所以,实际上gcc这个命令只是这些后台程序的包装,它会根据不同的参数要求去调用预编译编译程序ccl、汇编器as、连接器ld。

2.1.3 汇编

汇编器是将汇编代码转变成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令,只需根据汇编指令和机器指令的对照表一一翻译即可。

$ as hello.s -o hello.o
或者
$ gcc -c hello.c -o hello.o

这里,hello.o文件已经是二进制机器码,不能使用vim打开。但是可以使用nm命令打开,nm命令被用于显示二进制目标文件的符号表。

$ nm hello.o

目标文件符号表

2.1.4 链接

为什么汇编器不直接输出可执行文件而是输出一个目标文件呢?链接过程到底包含了什么内容?为什么要链接?

——《程序员的自我修养》

展开阅读全文

没有更多推荐了,返回首页