gcc 编译c文件的几个过程
https://www.cnblogs.com/zhangpengshou/p/3587751.html
http://m.elecfans.com/article/663750.html
https://www.cnblogs.com/LiuYanYGZ/p/5548855.html
https://blog.csdn.net/qq_33160790/article/details/78887349
c语言编译分为4个过程:
1:预编译:预编译做的事情为:把伪指令转换为实际指令 命令 gcc -E
a:#define a b
b:#条件编译指令,如#ifdef,#ifndef,#else,#elif,#endif等
c:#include 头文件加入到编译的文件中
d:一些符号处理如file local 等等;
# 1 "/usr/lib/gcc/x86_64-redhat-linux/4.4.7/include/stddef.h" 1 3 4 # 211 "/usr/lib/gcc/x86_64-redhat-linux/4.4.7/include/stddef.h" 3 4 typedef long unsigned int size_t; # 35 "/usr/include/stdio.h" 2 3 4 # 1 "/usr/include/bits/types.h" 1 3 4 # 28 "/usr/include/bits/types.h" 3 4 # 1 "/usr/include/bits/wordsize.h" 1 3 4 # 29 "/usr/include/bits/types.h" 2 3 4 typedef unsigned char __u_char; typedef unsigned short int __u_short; typedef unsigned int __u_int; typedef unsigned long int __u_long; typedef signed char __int8_t; typedef unsigned char __uint8_t; typedef signed short int __int16_t; typedef unsigned short int __uint16_t; typedef signed int __int32_t; typedef unsigned int __uint32_t; typedef signed long int __int64_t; typedef unsigned long int __uint64_t;
可以看出一个很小的程序经过编译以后把所有的头文件包含进来都是很大的
2:编译 命令是 gcc -S
把预编译好的文件逐条转化为汇编语言
优化阶段,经过预编译得到的输出文件中,只有常量;如数字、字符串、变量的定义,
以及c语言的关键字,如main,if,else,for,while,{,}, +,-,*,\等等。
编译程序所要作得工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,
将其翻译成等价的中间代码表示或汇编代码。如下都是汇编代码;操作寄存器
.file "test7.c" .text .globl power .type power, @function power: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl %edi, -20(%rbp) movl %esi, -24(%rbp) movl $1, -8(%rbp) movl -20(%rbp), %eax movl %eax, -4(%rbp) jmp .L2 .L3: movl -4(%rbp), %eax movl -20(%rbp), %edx imull %edx, %eax movl %eax, -20(%rbp) addl $1, -8(%rbp)
3:汇编 命令gcc -c
将.c文件直接编译成.o的二进制文件:
4:链接 命令是 gcc *.c 链接命令是ld 链接的时候要考虑代码和数据所要放的内存位置,可以通过链接脚本来设置(这里下次课再说)
链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够诶操作系统装入执行的统一整体。
根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种:
(1)静态链接
在这种链接方式下,函数的代码将从其所在地静态链接库中被拷贝到最终的可执行程序中。这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合,其中的每个文件含有库中的一个或者一组相关函数的代码。
(2) 动态链接
在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。链接程序此时所作的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的登记信息。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。
对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。但并不是使用动态链接就一定比使用静态链接要优越。在某些情况下动态链接可能带来一些性能上损害。
=====================
gcc -o 指定文件名 如 gcc -c hello.c -o hello.a
gcc -M 只输出编译信息不编译
gcc -MM 只输出编译信息不编译