一个c程序从源代码到可执行程序总共经历了4个步骤(以及对应的gcc 参数):
预编译(gcc -E),汇编(gcc -S),编译(gcc -c),以及链接(gcc)
以这个最简单的c程序为例:
fun.h头文件
//"func.h"
void func()
{
return 0;
}
#include "func.h"
#define TMP 1
int main()
{
int a = TMP;
return func()
}
gcc -o main.i -E main.c后输出
# 1 "main.c"
# 1 "<built-in>"
# 1 "<命令行>"
# 1 "main.c"
# 1 "func.h" 1
int func()
{
return 0;
}
# 2 "main.c" 2
int main()
{
int a = 1;
return func();
}
可以看出,预编译就是把程序包含的头文件原封不懂地放在源文件的上面,并把宏#define 等执行完
gcc -o main.s -S main.i 后输出
.file "main.c"
.text
.globl func
.type func, @function
func:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size func, .-func
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $0, %eax
call func
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-3)"
.section .note.GNU-stack,"",@progbits
看到,汇编这一步的作用就是把c语言转换成对应的汇编语言
然后运行gcc -o main.o -c main.s
此时如果在查看main.o中的内容,会发现出现一大堆乱码,此时,main.o已经是二进制的机器码了
此时如果在执行 gcc -o app main.o,执行链接即可得到可执行文件app
链接做的事就是把系统中或第三方的库(windows下一般为dll文件,linux下一般为so文件)链接到程序中(静态或动态),然后得到的文件就是可执行文件了~