引用文章链接:gcc编译过程简述
在Linux下运行C语言程序
在c语言基础中,使用gcc编译c语言过程一般如下:
gcc 源文件 -o 目标文件
如:
gcc hello.c -o hello
如果有多个源文件,可以这样来编译:
gcc test1.o test2.o -o test
上述命令可以直接将c语言文件编译链接为可执行文件
如果目标文件未指定,默认输入目标文件为a.out
在c程序设计语言一书中,作者介绍的是用cc命令去编译,通过从其他博客了解到:cc:C compiler,即c编译器,为unix系统的产物。gcc:GNU compiler collection。在Linux中,cc与gcc是同一个东西,cc是指向gcc的链接Linux 下 的 cc 和 gcc
在Mac系统中,cc是指向clang(苹果的c语言编译器)。
MacBook-Pro:~ james$ which cc
/usr/bin/cc
MacBook-Pro:~ james$ which gcc
/usr/bin/gcc
MacBook-Pro:~ james$ ls -al /usr/bin/cc
lrwxr-xr-x 1 root wheel 5 1 11 2017 /usr/bin/cc -> clang
关于这些区别暂时只讲这么多,接下来我们不用上面所列的一次完成的gcc命令,而是分布完成编译,体验一下c语言的编译过程。
首先,准备一个牛叉的c语言文件,文件名为hello.c,文件内容如下:
#include
int main(){
printf("hello world\n");
return 0;
}
这个源文件大小为71 B.
gcc -E hello.c -o hello.i
上面生成文件hello.i,文件大小为4,100B,这时预处理器将stdio.h的内容直接插入到程序中。(难道这就是称#include为预处理命令的原因?)
2. 编译为汇编代码
gcc -S hello.i -o hello.s
//生成的hello.s文件大小670B,文件内容如下:
.section
__TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 12
.globl _main
.p2align 4, 0x90
_main: ## @main
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp0:
.cfi_def_cfa_offset 16
Ltmp1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp2:
.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
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "hello world\n"
.subsections_via_symbols
这时生成的hello.s即为一个汇编程序
汇编语言是将不同高级语言的不同编译器提供了通用的输出语言。
3. 汇编为目标文件
gcc -c hello.s -o hello.o
//生成的hello.o文件大小768B,生成的文件内容如下:
cffa edfe 0700 0001 0300 0000 0100 0000
0400 0000 0002 0000 0020 0000 0000 0000
1900 0000 8801 0000 0000 0000 0000 0000
.........
2400 0000 1c00 0000 88ff ffff ffff ffff
2a00 0000 0000 0000 0041 0e10 8602 430d
0600 0000 0000 0000 1900 0000 0100 002d
0b00 0000 0200 0015 0000 0000 0100 0006
0100 0000 0f01 0000 0000 0000 0000 0000
0700 0000 0100 0000 0000 0000 0000 0000
005f 6d61 696e 005f 7072 696e 7466 0000
鬼知道这里是啥意思,这是一个二进制文件。离成为可执行文件只差链接库了。
4. 链接并生成可执行文件
gcc hello.o -o hello
//生成hello,文件大小8,432B,打开内容也是二进制
cffa edfe 0700 0001 0300 0080 0200 0000
0f00 0000 b004 0000 8500 2000 0000 0000
1900 0000 4800 0000 5f5f 5041 4745 5a45
524f 0000 0000 0000 0000 0000 0000 0000
0000 0000 0100 0000 0000 0000 0000 0000
........
//这中间有至少50行全为0
0000 0040 0200 0000 2000 5f5f 6d68 5f65
7865 6375 7465 5f68 6561 6465 7200 5f6d
6169 6e00 5f70 7269 6e74 6600 6479 6c64
5f73 7475 625f 6269 6e64 6572 0000 0000
生成的hello文件可以运行如下:
MacBook-Pro:c james$ ./hello
hello world
总结:
编译器的编译过程:
源文件-->预处理-->编译/优化-->汇编-->链接–>可执行文件。
一个最简单的hello world,电脑帮我们做了这么多事情,看来也不容易啊。