gcc是linux上常用的编译工具,其实质上不是一个单独的程序,而是多个程序的集合,因此称为工具链;
程序的预处理、编译、执行过程
①预处理:c语言的源文件(.c)先通过预处理器进行预处理,主要处理#include语句包含的文件内容替换、#define定义的宏变量替换、删除所有的注释,生成.i的预处理文件,命令是gcc -E hello.c -o hello.i
②编译:将上述预处理文件通过编译器得到目标文件(.o),可以同时对多个预处理文件、源文件处理,命令是gcc -c hello.c -o hello.o
③链接:得到的目标文件需要经过链接器与系统提供的启动代码链接起来才能正常运行;就是说将各个目标文件和库里的可执行文件链接起来,哪怕只有一个文件也需要与标准库进行链接(需要标准输出、输入等函数的执行文件)
gcc命令用法
gcc | -o | 确定输出文件的文件名 |
-E | 得到预处理后的.i文件 | |
-C | 保留注释 | |
-c | 输出得到.o的目标文件(不链接库,但可以放到库里) | |
-S | 对.c和.i处理,生成汇编文件.s | |
-g | 生成调试版的可执行文件 | |
-O | 对代码进行优化编译,从哦、O0~O3四个等级,优化能力逐步提高,默认O1 | |
-I+directory | 告诉gcc去哪里找头文件(例:-I ../ 就是去父目录去找) |
静态库与动态库的区别
程序库:包含通用函数的数据和二进制可执行文件(.o);通常将频繁使用的功能封装成函数,人后经过gcc编译得到可执行文件后(.o),放到库里,方便后续直接调用;注意主函数不能放到库里;又分为静态库与动态库;
静态库(以空间换时间)(格式:.a):是在执行程序之前就已经加入到执行代码中,成为执行文件的一部分来执行的;优点:程序运行快;缺点:会造成程序臃肿,难以升级(需要重新编译后放入库里);
动态库(以时间换空间)(格式:.so):是在执行程序启动是加载到执行代码中;优点:不会增加源程序的大小,且可以被多个程序使用,别称共享库,容易升级;缺点:加载时间长,造成程序运行等待;
静态库的创建
①gcc -c add.c //生成add.0可执行文件
②gcc -c sub.c //生成sub.o可执行文件
③... //生成多个可执行文件
④ar rcs libmath.a add.o sub.o ...(如果还有的话) //生成libmath.a的静态库,其中rc是指静态库不存在就创建该库文件,s是指更新库文件
⑤gcc main.c -o main -L. -libmath.a -I../ //-L是告诉库在当前目录(.),-I../是告诉gcc到父目录(../)去找新增的头文件,如果在当前目录则为-I./(少一个点)
⑥./main //执行程序
动态库的创建
①gcc -shared -fPIC -o libmath.so add.c sub.c ...(如果还有其他源文件的话) //一步到位,相当于静态库的1-4步骤
②gcc main.c ./libmath.so -o main -I../ //-I../是告诉gcc到父目录(../)去找新增的头文件,如果在当前目录则为-I./(少一个点)