gcc编译的过程

简介: GCC 仅仅是一个编译器,没有界面,必须在命令行模式下使用。通过 gcc 命令就可以将源文件编译成可执行文件。

前言


GCC 仅仅是一个编译器,没有界面,必须在命令行模式下使用。通过 gcc 命令就可以将源文件编译成可执行文件。


一个C/C++文件要经过预处理(preprocessing)、编译(compilation)、汇编(assembly)和链接(linking)等4步才能变成可执行文件,通常使用“编译”统称这4个步骤。


一、gcc 编译四步骤



二、gcc编译常用参数


-I 指定头文件所在目录位置
-c 只做预处理,编译,汇编。得到二进制文件
-g 编译时添加调试文件,用于 gdb 调试
-Wall 显示所有警告信息
-D 向程序中“动态”注册宏定义
-l 指定动态库库名
-L 指定动态库路径


三、文件后缀名对应表


后缀名 类型
.c c源程序
.h 预处理器文件
.cpp c++源程序
.i 预处理后的c文件
.ii 预处理后的c++文件
.s 汇编语言源程序
.o 目标文件(Object file)
.a 静态链接库文件(linux)
.so 动态链接库文件(linux)
.lib 静态链接库文件(windows)
.dll 动态链接库文件(windows)


四、预处理


预处理是读取 c 源程序,对其中的伪指令(以 # 开头的指令,也就是宏)和特殊符号进行“替代”处理;经过此处理,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出文件。这个文件的含义同没有经过预处理的源文件是相同的,仍然是 C 文件,但内容有所不同。


预处理主要包括以下过程:


将所有的 #define 删除,并且展开所有的宏定义

处理所有的条件预编译指令,比如 #if #ifdef #elif #else #endif 等

处理 #include 预编译指令,将被包含的文件插入到该预编译指令的位置。

删除所有注释 “//”和”/* */”.

添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。

保留所有的 #pragma 编译器指令,因为编译器需要使用它们


下面我们将一端简单的C代码做示例。

/* --------普通的c代码----------*/
#include <stdio.h>
#define COUNTE 5
int main(int argc,char ** argv)
{
    for(int i=0; i <= COUNTE; i++) {
        printf("hello world!\n");
    }   
    return 0;
}

然后经过预处理:

gcc -E hello.c -o hello.i

其注释被删除,且宏也被替代之后删除,如下图所示。


五、编译


编译程序所要作的工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码

 gcc -S hello.i -o hello.s

不同的编译器交叉编译同一个 hello.i 文件生成的汇编文件也不相同,这也是 C 语言可移植性的一种体现。


六、汇编


汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。对于被翻译系统处理的每一个 C 语言源程序,都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。 目标文件由段组成。通常一个目标文件中至少有两个段:


代码段(文本段):该段中所包含的主要是程序的指令。该段一般是可读和可执行的,但一般不可写;

数据段:主要存放程序中要用到的各种常量、全局变量、静态的数据。一般数据段都是可读,可写,可执行的;


gcc -c hello.s -o hello.o  

因为翻译成了计算机可以识别的二进制文件,因此乱码。


七、链接


汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。 链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体,也就是可执行程序。 根据开发人员指定的库函数的链接方式的不同,链接处理可分为两种:


静态链接

动态链接


1、静态链接


静态链接的优点:

(1)装载速度很快,运行速度比动态链接快;

(2)只需要开发人员在开发机上有完整的.lib文件,不需要在用户机器上有完整的.lib文件,自完备


静态链接的缺点:

(1)可执行文件很大,并且相同代码很多,资源浪费


动态链接编译:

gcc hello.o -o hello -static


2、动态链接


动态链接的优点:

(1)可执行文件很小;

(2)适合大规模软件开发,开发过程耦合度小、独立,便于不同开发人员和开发组织开发;

(3)不同编程语言按照约定可以使用同一套.dll库;


动态链接的缺点:

(1)速度没有静态链接快;

(2)不具有自完备,如果用户机器中没有.dll文件,程序将无法运行并且报错


动态链接编译:

gcc hello.o -o hello


目录
相关文章
|
1月前
|
编译器 Linux 开发工具
|
22小时前
|
自然语言处理 编译器 Go
GCC:GNU编译器
GCC:GNU编译器
6 0
|
23小时前
|
Java 编译器 Linux
技术经验解读:【转载】详解GCC的下载和安装(源码安装)
技术经验解读:【转载】详解GCC的下载和安装(源码安装)
|
11天前
|
C语言
关于如何解决mingw64安装后配置完环境变量仍然执行不了gcc命令
关于如何解决mingw64安装后配置完环境变量仍然执行不了gcc命令
|
1月前
|
C语言
gcc的简易用法
【5月更文挑战第10天】gcc的简易用法。
30 8
|
1月前
|
C语言
gcc的简易用法(编译、参数与链接)
【5月更文挑战第14天】gcc的简易用法(编译、参数与链接)。
22 1
|
1月前
|
Unix Java 编译器
安装gcc
【5月更文挑战第14天】安装gcc。
44 1
|
1月前
|
C语言
转载 - gcc/ld 动态连接库和静态连接库使用方法
本文介绍了如何在GCC中实现部分程序静态链接、部分动态链接。使用`-Wl`标志传递链接器参数,`-Bstatic`强制链接静态库,`-Bdynamic`强制链接动态库。
52 0
|
1月前
|
编译器 C语言 C++
列举gcc 常见和有用的编译警告选项
列举gcc 常见和有用的编译警告选项
38 0
|
1月前
|
NoSQL 编译器 开发工具
006.gcc编译器
gcc是什么?
55 0
006.gcc编译器