目录一、GCC C语言编译器1.1 阶段1预处理编辑1.2 阶段 2编译Compilation1.3 阶段 3汇编Assembly1.4 阶段 4链接Linking二、GCC核心功能2.1 条件翻译(仅了解)2.2 静态链接 和 动态链接2.3 查看依赖的库文件GCC将C源码编译为可执行文件经历预处理展开头文件、宏替换、条件编译、编译生成汇编代码、汇编生成目标文件.o和链接合并目标文件与库生成可执行程序四阶段。支持静态链接代码复制到可执行文件独立运行但体积大和动态链接运行时加载库节省空间但依赖系统库。通过ldd可查看动态依赖库-E、-S、-c等选项分别控制预处理、编译、汇编阶段输出。一、GCC C语言编译器编译过程的本质将源文件翻译成可执行二进制文件。1.1 阶段1预处理文件后缀.i处理以#开头的预处理指令#include把头文件内容直接复制粘贴进当前源码#define宏替换把代码里宏名全部替换成对应文本#ifdef / #endif条件编译保留 / 删除指定代码段删除注释// 单行注释、/* */ 多行注释全部清除添加行号信息方便后续报错定位gcc -E test.c -o test.i首先创建code.c并输入如下内容1 #includestdio.h 2 3 #define M 100 4 int main() 5 { 6 printf(hello %d\n,M); 7 //printf(hello %d\n,M); 8 //printf(hello %d\n,M); 9 //printf(hello %d\n,M); 10 //printf(hello %d\n,M); 11 //printf(hello %d\n,M); 12 printf(hello %d\n,M); 13 }如果直接编译将看不到翻译过程[kkkVM-0-4-centos ~]$ gcc code.c -o code.exe //-o 明确新文件的名称 [kkkVM-0-4-centos ~]$ ll total 36 -rwxrwxr-x 1 kkk kkk 8360 Oct 6 21:37 a.out -rw-rw-r-- 1 kkk kkk 309 Oct 6 21:37 code.c -rwxrwxr-x 1 kkk kkk 8360 Oct 6 21:39 code.exe -rw-rw-r-- 1 kkk kkk 827 Oct 6 21:08 install.sh -rw-rw-r-- 1 kkk kkk 47 Oct 6 21:14 test.c预处理指令gcc -E code.c -o code.i将翻译过程放到code.i的临时文件中-E表示预处理后停下-o后跟预处理的结果预处理的工作头文件展开、去注释、宏替换、条件编译如图预处理后的文件非常长头文件展开就是把头文件相关内容拷贝到源文件头源合并的过程编译器只需要再预处理时需要头文件1.2 阶段 2编译Compilation文件后缀.s把预处理后的.i文件翻译成汇编代码汇编语言文本人可读但还不能直接运行gcc -S test.i -o test.s-S执行到编译阶段输出汇编.s文件1.3 阶段 3汇编Assembly文件后缀.o目标文件.o: .obj可重定位二进制目标文件汇编器 as将汇编代码翻译成机器码二进制目标文件已经是二进制但缺少函数地址链接不能直接运行gcc -c test.s -o test.o-c执行到汇编输出目标文件.o1.4 阶段 4链接Linking输出可执行文件无后缀Linux 下将多个.o目标文件 系统库文件libc合并解析符号、补齐函数地址比如printf在 C 标准库里面生成最终可以直接执行的程序日常开发中GCC会直接一键完成这四个阶段ESc - iso二、GCC核心功能2.1 条件翻译(仅了解)属于预处理阶段的内容gcc -E 的时候就生效编译前就决定哪些代码保留、哪些直接删掉核心语法#ifdef 宏名 // 如果宏已经被定义保留这段代码 #else // 宏没定义保留这段 #endif#ifndef 宏名 // 如果宏【没有】被定义保留这段 #else // 宏已经定义 #endif#ifndef 最常见用途头文件防止重复包含头文件保护宏简单例子#include stdio.h #define DEBUG 1 #ifdef DEBUG printf(调试信息进入函数\n); #endif int main(){ printf(hello\n); return 0; }2.2 静态链接 和 动态链接链接是编译四步的最后一步把.o目标文件 库 合并生成可执行程序。库分为两种静态库.a、动态库.soLinux 下静态链接静态库 .a原理链接的时候把库里面用到的代码直接复制拷贝到你的可执行文件内部。 程序生成后不再依赖原静态库文件。gcc test.c -o test_static -static #强制静态链接生成可执行文件(因为GCC默认是动态链接的)安装命令sudo yum install glibc-static libstdc-static -y优点可执行文件不依赖系统库移植性强。缺点会让可执行程序变大运行的时候加载到内存占据更多的内存空间浪费资源动态链接动态共享库 .so原理链接阶段不拷贝库代码只记录库名和符号。 等到程序运行的时候操作系统再把动态库加载到内存多个程序可以共享同一份内存里的库。Linux 默认 gcc 就是动态链接gcc test.c -o test_dynamic优点文件体积小库文件被多个程序共享节省内存和磁盘空间缺点依赖系统中对应的库文件一旦库文件缺失所有程序都无法运行了。2.3 查看依赖的库文件# 查看程序依赖哪些动态库动态链接专用 ldd test_dyn # 静态编译出来的程序ldd会提示不是动态可执行文件 ldd test_static以上就是本期的全部内容感谢你能够看到这里