所有的c语言,编写完成后,生成可执行文件都有以下几个步骤。

1.预处理,将所有的#define删除,并且展开所有的宏定义。处理#if,#ifdef,#else等。以及#include,以及删除所有注释。添加行号和文件标识方便下一步编译。将引入的头文件进行处理。

2.编译:这一步主要是将预处理生成的文件(.i)生成汇编语言,这一步很重要。不同版本的gcc,比如gcc-x86,arm-linux-gcc(交叉编译器)。会将预处理生成的文件编译成不同的汇编指令集。

3.汇编:这个步骤将上面编译出来的汇编指令变成二进制机器码。生成目标文件(.o)

4.链接:这一步最重要,编写的c语言文件又很多个,以及要引用到libc库或者其他库中的文件比如(stdio.h)文件。这一步要将他们链接到一起。最后生成可执行文件。

在linux中,安装gcc工具链。

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

预处理过程,gcc命令

gcc -E test.c -o test.i

    //文件内容多,不展示

编译过程,gcc命令

gcc -S test.i -o test.s

	.file	"demo01-gcc-test.c"
	.text
	.section	.rodata
.LC0:
	.string	"hello world!"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	endbr64
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	leaq	.LC0(%rip), %rax
	movq	%rax, %rdi
	call	puts@PLT
	movl	$0, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0"
	.section	.note.GNU-stack,"",@progbits
	.section	.note.gnu.property,"a"
	.align 8
	.long	1f - 0f
	.long	4f - 1f
	.long	5
0:
	.string	"GNU"
1:
	.align 8
	.long	0xc0000002
	.long	3f - 2f
2:
	.long	0x3
3:
	.align 8
4:

汇编过程指令

gcc -c test.s -0 test.o

链接过程命令

//这一步因为涉及很多个文件

一步到位生成可执行文件

gcc test.c -o test //直接生成可执行文件test 为文件test分配执行权限后,执行./test 打印hello word!

GCC 基本用法

GCC 的基本命令格式如下:

gcc [选项] [文件名]
其中,[选项] 用于指定编译行为,[文件名] 是需要编译的源文件。

常用选项

-o [文件名]:指定输出文件名,默认生成 a.out。

-c:只编译生成目标文件(.o 文件),不进行链接。

-S:生成汇编代码文件(.s 文件)。

-E:只进行预处理,输出预处理结果。

-g:生成调试信息,便于使用调试工具(如 GDB)。

-O0/-O1/-O2/-O3:优化级别,-O0 表示无优化,-O3 优化级别最高。

-Wall:启用所有警告信息。

-static:使用静态链接库,生成独立的可执行文件。

-shared:生成共享库文件。

GCC 编译过程

GCC 的编译过程分为以下四个步骤:

预处理:展开宏定义、头文件等,生成 .i 文件。

gcc -E hello.c -o hello.i
编译:将预处理后的代码转为汇编代码,生成 .s 文件。

gcc -S hello.i -o hello.s
汇编:将汇编代码转为目标文件(机器码),生成 .o 文件。

gcc -c hello.s -o hello.o
链接:将目标文件与库文件链接,生成可执行文件。

gcc hello.o -o hello