C编译过程

1,358 阅读2分钟

c的编译过程整体分为4个步骤

1. 预编译

预编译的过程主要处理相关的c文件,主要处理c文件涉及的相关的预编译指令,比如#include, #define, 条件编译#if #ifdef等等。

在预编译阶段会进行宏展开,预编译完成后的文件不再包含任何的宏定义

预编译指令

# 针对hello.c预编译指令如下
gcc -E hello.c -o hello.i

2. 编译

编译过程就是一系列的词法分析、语法分析将预编译完成的文件转化为汇编文件

编译指令

# 针对hello.c编译指令如下, hello.c 预编译产生hello.i文件
gcc -S hello.i -o hello.s

查看一下简单的hello world 文件生成的汇编指令

 cat hello.s
	.section	__TEXT,__text,regular,pure_instructions
	.build_version macos, 11, 0	sdk_version 11, 1
	.globl	_main                   ## -- Begin function main
	.p2align	4, 0x90
_main:                                  ## @main
	.cfi_startproc
## %bb.0:
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset %rbp, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register %rbp
	subq	$32, %rsp
	movl	%edi, -4(%rbp)
	movq	%rsi, -16(%rbp)
	leaq	L_.str(%rip), %rdi
	movb	$0, %al
	callq	_printf
	xorl	%ecx, %ecx
	movl	%eax, -20(%rbp)         ## 4-byte Spill
	movl	%ecx, %eax
	addq	$32, %rsp
	popq	%rbp
	retq
	.cfi_endproc
                                        ## -- End function
	.section	__TEXT,__cstring,cstring_literals
L_.str:                                 ## @.str
	.asciz	"Hello World"

.subsections_via_symbols

3. 汇编

汇编器会将编译生成的汇编文件翻译成对应的机器指令

汇编指令

# 针对上文hello.s通过汇编指令生成hello.o
gcc -c hello.s -o hello.o
#hello.o 即是日常所说的目标文件

4. 链接

链接即是将上文生成的目标文件转化为可执行文件,链接过程比较复杂,涉及目标文件依赖分析替换,地址变更等

链接指令

ld # 链接器需要指定对应的头文件
gcc编译器常见语法:

-c:只进行编译,不进行链接,输出的是与源文件同名的.o文件。

-o:指定生成的文件的名称。链接生成可执行文件,这个参数后可以带可执行文件的名字,如果没有指定可执行文件的名字,则会默认为a.out。

-S:输出汇编代码文件,输出一个与源文件同名的.s文件,这个文件中的内容为汇编程序。

-O:在编译链接的过程中进行优化,在编译过程中对代码进行优化,代码经过优化后再利用汇编程序翻译成目标代码。