linux c
gcc
gcc编译可以执行4步骤:预处理、编译、汇编、链接
预处理 gcc -E
hello.c----->hello.i
展开宏、头文件,替换条件编译,删除注释、空行、空白
编译 gcc -S
hello.i------>hello.s
检查语法规范
汇编 gcc -c
hello.s------>hello.o
将汇编指令翻译成机器指令
链接 (无参数)
hello.o----->a.out
数据段合并地址回填
-o不是链接阶段的参数是起名的
- 编译阶段消耗时间、和系统资源最多
常用参数
-v查看gcc版本号
-version
-I目录指定头文件
当头文件和源码不在一级目录下,就需要指定头文件的位置
hello.c包含hello.h,hello.h在inc目录下
-I放在编译的前面和后面都可以
gcc -I ./inc hello.c -o hello
静态库和动态库
库可以提高程序编写速度,提高效率
静态库
占内存,速度快
使用在对空间要求较低,对时间要求较高的核心程序中(操作系统启动例程)
制作静态库
ar rcs libmylib.a(起名必须以.a结尾,lib开头) file1.o
- 将 .c 生成 .o 文件 gcc -c add.c -o add.o
- 使用ar工具制作你静态库 ar rcs lib库名.a add.o sub.o div1.o
- 编译到可执行文件中:gcc test.c lib库名.a -o a.out
共享库(动态库)
省内存,速度慢
对时间较低,对空间要求较高
制作动态库
- 将 .c 生成 .o 文件,需要生成与位置无关的代码(-fPIC)gcc -c add.c -o -fPIC
- 使用gcc -shared 制作动态库 gcc -shared lib库名.so add.o sub.o div1.o
- 编译可执行程序时指定所使用的动态库. -l ,指定库名,-L,指定库路径 gcc test.c -o a.out -l mymath -L /lib
- 运行可执行程序./a.out,出错原因:
链接器: 工作于链接阶段,工作时需要 -l 和 -L
动态连接器: 工作于程序运行阶段,工作时需要提供动态库所在目录位置
要 -l 和 -L
动态连接器: 工作于程序运行阶段,工作时需要提供动态库所在目录位置
[外链图片转存中…(img-Nuy1sGcf-1683213588529)]
静态函数有位置,动态函数没有位置,动态函数的位置取决于@plt,@plt在动态库加载到内存的时候被填充,动态库的函数比自己定义的函数绑定地址的时间比晚,即plt是一个基地址,需要动态库加载到内存才能确定,而调用的函数是相对于动态库的一个偏移地址。而调用函数的绝对地址是plt的基地址加上偏移地址确定的