C 语言从源代码变成可执行文件经过了以下步骤: 预处理(preprocessing)、编译(compilation)、汇编(assembly)、和连接(linking).
下面, 我们以 hello.c 为例, 看一下整个链接过程.
hello.c
#include <stdio.h>
int main() {
printf("hello world\n");
return 0;
}
-
预处理 ==> .c -> .i
预处理包含有以下三种操作
- 将要包含(include)的文件插入原文件中
- 将宏定义展开
- 根据条件编译命令选择要使用的代码操作
$ gcc -E hello.c -o hello.i
由于最后的预处理后的 .i 文件过大, 这里只展示一部分:
# 1 "hello.c" # 1 "<built-in>" 1 # 1 "<built-in>" 3 I# 68 "/usr/include/_stdio.h" 3 4 # 1 "/usr/include/sys/cdefs.h" 1 3 4 # 587 "/usr/include/sys/cdefs.h" 3 4 # 1 "/usr/include/sys/_symbol_aliasing.h" 1 3 4 # 588 "/usr/include/sys/cdefs.h" 2 3 4 # 653 "/usr/include/sys/cdefs.h" 3 4 # 1 "/usr/include/sys/_posix_availability.h" 1 3 4 ....... extern int __vsnprintf_chk (char * restrict, size_t, int, size_t, const char * restrict, va_list); # 412 "/usr/include/stdio.h" 2 3 4 # 2 "hello.c" 2 int main() { printf("hello world\n"); return 0; }
-
编译 ==> .i -> .s
编译过程是将上面预处理过后的文件翻译成汇编代码.
$ gcc -S hello.i -o hello.s $ vi hello.s .section __TEXT,__text,regular,pure_instructions .macosx_version_min 10, 13 .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 $16, %rsp leaq L_.str(%rip), %rdi movl $0, -4(%rbp) movb $0, %al callq _printf xorl %ecx, %ecx movl %eax, -8(%rbp) ## 4-byte Spill movl %ecx, %eax addq $16, %rsp popq %rbp retq .cfi_endproc ## -- End function .section __TEXT,__cstring,cstring_literals L_.str: ## @.str .asciz "hello world\n" .subsections_via_symbols
-
汇编 ==> .s -> .o
将汇编代码翻译成符合一定格式的机器代码.
gcc -c hello.s -o hello.o
-
链接 ==> .o -> app
链接就是将汇编生成的OBJ文件、系统库的OBJ文件、库文件链接起来,最终生成可以在特定平台运行的可执行程序.
gcc hello.o -o app
网友评论