gcc编译四个阶段:预处理、编译、汇编、链接

(一)gcc/g++介绍

gcc/g++是编译系统的驱动程序,负责解析输入的参数。
依次调用预处理器(cpp)、编译器(ccl/cclplus)、汇编器(as)、链接器(ld),
执行四个阶段,最终生成可执行文件。

(二)gcc和 g++ 的区别

gcc把 .c程序文件当C代码处理(ccl编译)。
g++把 .c程序文件当作 C++ 处理(cclplus编译)。

对于 .cpp程序文件,gcc和 g++ 处理过程没有区别。

gcc不能直接编译 C++ 程序的,需要加上-lstdc++。
g++可以直接编译C++程序,g++相当于是对gcc的封装。

(三)gcc hello.c 生成a.out,需要四个步骤:

第一步:预处理(Prepressing)

工具:预处理器 cpp
将源代码转换为预处理文件,生成.i或者.ii文件

第二步:编译(Compilation)

工具:编译器 ccl/cclplus
将预处理文件转换为汇编文件,生成.s文件

第三步:汇编(Assembly)

工具:汇编器 as
将汇编文件转换为目标文件,生成.o文件(二进制文件)

第四步:链接(Linking)

工具: 链接器 ld
将目标目标文件链接为可执行文件,生成.out文件

  源文件          预处理文件          汇编文件          目标文件          可执行文件
.c /.cpp   ===>   .i/.ii      ===>    .s       ===>    .o      ===>   .out
           预处理              编译              汇编            链接
          预处理器cpp    编译器ccl/cclplus       汇编器as        链接器ld 

GCC编译过程
在介绍GCC编译步骤之前,首先需要了解GCC支持的后缀文件类型。

.c 是C程序文件。
.c/.cc/.cxx是C++程序文件。
.i 预处理后的C程序文件,.ii 预处理后的C++程序文件。
.s/.S 是汇编语言程序。
.h 是头文件。
.o 是目标文件。
.a 是静态库文件
.so 是动态库文件。

GCC编译流程分为四个步骤:
预处理(生成.i/.ii文件)、编译(生成.s/.S文件)、汇编(生成.o文件)、链接(生成.out文件)。

gcc指令的一般格式为:
gcc [选项] 要编译的文件 [选项] [目标文件]
其中,目标文件可缺省,gcc默认生成可执行的文件为a.out

#include <stdio.h>
int main()
{
    printf("Hello World\n");
    return 0;
}

1、预处理

对于该阶段,gcc将stdio.h文件中的代码包含进这段程序,
我们可以利用
gcc -E test.c -o test.i
命令来生成预处理过的.i文件。
-E选项代表让gcc在预处理阶段后停止编译。

test.i文件中的内容如下所示,可以看出stdio.h文件中的内容被展开。

extern int fprintf (FILE *__restrict __stream,
  __const char *__restrict __format, ...);
  ......
  # 8 "test.c" 2
int main()
{
    printf("Hello World\n");
    return 0;
}

2、编译

该阶段主要是对预编译后的.i文件编译,生成汇编文件(.s文件)。
gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作。
在检查无误后,gcc把代码翻译成汇编语言。

我们可以使用-S选项来进行查看,该选项只进行编译而不进行汇编过程,生成汇编代码。
我们可以利用
gcc -S test.i -o test.s
命令进行编译过程。

test.s文件中的内容如下所示。

 .file   "test.c"
    .section    .rodata
.LC0:
    .string "Hello World"
    .text
.globl main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    movl    $.LC0, (%esp)
    call    puts
    movl    $0, %eax
    leave
    ret
    .size   main, .-main
    .ident  "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-16)"
    .section    .note.GNU-stack,"",@progbits

3、汇编

该阶段是将编译后的.s文件转化成二进制文件.o的过程
利用-c选项就可以生成二进制.o文件。
我们可以利用
gcc -c test.s -o test.o
命令生成二进制代码。

4、链接

该阶段主要将成功编译的二进制文件进行链接操作,生成可执行文件。
利用
gcc test.o -o test.out
命令生成可执行文件test.out。
运行./test.out即可打印出hello world。

总结一下:
gcc -E test.c -o test.i 把原代码交给cpp预处理器生成预处理文件(test.i文件)
gcc -S test.i -o test.s 把经过预处理之后的test.i文件交给编译器cc1生成汇编文件(test.s文件)
gcc -c test.s -o test.o 把经过编译后汇编文件test.s交给as进行汇编,生成目标文件(test.o文件)
gcc test.o -o test 把as汇编之后的目标文件test.o交给ld链接成一个可执行文件(test.out文件)

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值