c语言编译过程及对应命令
程序员文章站
2022-06-04 13:16:07
...
以前搞编程都是IDE,虽然也知道编译这么几个步骤,但如何实现还真不是太清楚,工作在搞linux内核驱动开发,平时做个实验也只是:gcc hello.c -o hello
。
前段时正好在看些汇编,也就顺便学习了这些,趁着没事,分享一下。
0、源代码
#include <stdio.h>
int main(void){
printf("hello_world");
return 0;
}
1、预处理
gcc -E hello.c -o hello.i
实质上是处理“#”,将#include包含的头文件直接拷贝到hell.c当中;将#define定义的宏进行替换,同时将代码中没用的注释部分删除等
具体做的事儿如下:
- 将所有的#define删除,并且展开所有的宏定义,说白了就是字符替换
- 处理所有的条件编译指令,#ifdef #ifndef #endif等,就是带#的那些
- 处理#include,将#include指向的文件插入到该行处删除所有注释
- 添加行号和文件标示,这样的在调试和编译出错的时候才知道是是哪个文件的哪一行
- 保留#pragma编译器指令,因为编译器需要使用它们。
# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "hello.c"
# 1 "G:/mingw64/x86_64-w64-mingw32/include/stdio.h" 1 3
# 9 "G:/mingw64/x86_64-w64-mingw32/include/stdio.h" 3
# 1 "G:/mingw64/x86_64-w64-mingw32/include/crtdefs.h" 1 3
# 10 "G:/mingw64/x86_64-w64-mingw32/include/crtdefs.h" 3
# 1 "G:/mingw64/x86_64-w64-mingw32/include/_mingw.h" 1 3
# 12 "G:/mingw64/x86_64-w64-mingw32/include/_mingw.h" 3
.....
.....
.....
# 1400 "G:/mingw64/x86_64-w64-mingw32/include/stdio.h" 2 3
# 2 "hello.c" 2
# 2 "hello.c"
int main(void){
printf("hello_world");
return 0;
}
2、编译
gcc -S hello.i -o hello.s
这里可以将hello.i换成hello.c
编译的过程实质上是把高级语言翻译成汇编语言的过程,即对hello.c做了这些事儿
- 词法分析
- 语法分析
- 语义分析
- 优化后生成相应的汇编代码
高级语言->汇编语言
$ cat hello.s
.file "hello.c"
.text
.def __main; .scl 2; .type 32; .endef
.section .rdata,"dr"
.LC0:
.ascii "hello_world\0"
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
call __main
leaq .LC0(%rip), %rcx
call printf
movl $0, %eax
addq $32, %rsp
popq %rbp
ret
.seh_endproc
.ident "GCC: (x86_64-posix-sjlj-rev0, Built by MinGW-W64 project) 8.1.0"
.def printf; .scl 2; .type 32; .endef
3、汇编
gcc -c hello.s -o hello.o
这里可以将hello.s换成hello.c
这个过程就是把汇编指令翻译成机器语言(二进制文件)
$ nm -C hello.o
0000000000000000 b .bss
0000000000000000 d .data
0000000000000000 p .pdata
0000000000000000 r .rdata
0000000000000000 r .rdata$zzz
0000000000000000 t .text
0000000000000000 r .xdata
U __main
0000000000000000 T main
U printf
4、链接
gcc hello.c -o hello
最后就是链接,也就是把将翻译成的二进制与需要用到库绑定在一块,生成可执行文件。这时间的hello.o是不能执行的,hello是可以的。
$ ./hello
hello_world
下一篇: nginx 1.10.2 安装