函数的宏定义与常用的函数库

从源码到可执行程序的生产过程:
源码(.c文件)->经过预处理,变为.i源文件->经过编译,变为.S汇编文件->经过汇编,变为.O目标文件->经过链接,变为.elf可执行程序。
可简单理解为:将.C源文件经过编译(包括汇编)可以得到.O目标文件,将.O目标文件经过链接可以得到.elf的可执行文件。
1、gcc xx.c -c -o xx.o //将xx.c源文件只编译获得xx.o目标文件
2、gcc -E xx.c -o xx.i //将xx.c源文件只预处理获得xx.i源文件(多用于研究预处理过程,帮助debug程序)
常见的放在预处理中处理的:
1、头文件(#include<>和#include" “)
2、注释
3、#if #elif #endif #ifdef
4、宏定义
头文件的使用:
<>专门用来包含系统提供的头文件,” "用来包含自己写的头文件。
编译器中允许使用 -I 来附加指定路径去寻找头文件。
头文件的使用就是将头文件中的内容原地展开替换。
带参宏与内联函数:
带参宏:
带参宏的使用与带参函数类似,所不一样的是在使用带参宏的时候每个参数在宏体中引用时都必须加括号,最后整体再加一个括号。
eg:利用MAX宏,来求2个数中的较大一个
#define MAX(a,b) (((a)>(b))?(a):(b))
利用宏定义来表示一年中有多少秒。
#define SEC_PER_YEAR (3652460*60UL)
注:重点在于UL,表示无符号数,因为一年中的秒数刚好超出了int所能表示的范围。
带参宏与带参函数的区别:
带参宏是原地展开,没有调用开销,但不会检查参数的类型。
带参函数是跳转执行然后返回,由调用开销,但检查参数的类型。
内联函数(inline):
相当于带来参数静态检查的宏(即无开销调用,也有参数检查)。
常用函数库:
静态链接库
将源文件只编译不链接生成.O目标文件,然后用ar工具将.O文件归档成.a的归档文件(.a的归档文件又叫静态链接库)。发布的时候将.a与.h头文件一起发布;客户在使用的时候,通过头文件得知库中的库函数的原型,然后在自己的.c文件中直接调用这些库文件,在链接的时候链接器会去.a文件中拿出来被调用的那个函数的编译后的.o二进制代码段链接进去形成可执行程序。
动态链接库:
动态链接库本身不将库函数的代码段链接入可执行程序,只是做个标记。然后当应用程序在内存中执行时,运行时环境发现它调用了一个动态库中的库函数时,会去加载这个动态库到内存中,然后不管以后有多少个应用程序去调用这个库中的函数,都会跳转到第一次加载的地方去执行,不会重复调用。
库函数使用注意事项:
1、包含相应的头文件
2、注意函数原型
3、有些库函数在链接时需要额外用 -lxxx 来知道链接
4、动态库在使用时要注意用 -L 指定动态库的地址
链接时可以用 -lxxx 来指示链接器到libxxx.so中去查找这个函数;
-lm就是告诉链接器到libm中去查找用到的函数。
举例说明:
自己制作静态链接库,并使用:
制作静态链接库:
第一步:gcc mylib.c -c -o mylib.o
第二步:使用ar工具进行打包成.a归档文件ar -rc libmylib.a mylib.o
(ar为工具,rc为方法,libmylib.a为目标文件,mylib.o为源文件,一般库名在命名时为lib+库名)
静态链接库使用:
第一步:将.a与.h都放在我所引用的文件夹下,然后在自己编写的头文件中包含.h头文件。
第二步:编译链接时用gcc test.c -o text -lmylib -L.(-lmylib表示所要的库函数到libmylib中去找,-L.表示libmylib库在当前目录中)
制作动态链接库:
第一步:gcc mylib.c -o mylib.o -c -fPIC(-fPIC表示位置无关码)
第二步:gcc -o libmylib.so mylib.o -shared(-shared表示按照共享库的方式来链接)
动态链接库的使用:
第一步:将mylib.so放到系统默认的目录下(/usr/lib)或将mylib.so所在的目录路径导出到环境变量LD_LIBRARY_PATH中(导出方式为export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:mylib.so所在的目录路径)
第二步:编译链接时用gcc test.c -o test -lmylib -L.

发布了19 篇原创文章 · 获赞 11 · 访问量 3394

猜你喜欢

转载自blog.csdn.net/m0_46204326/article/details/104278513