老生常谈C语言静态函数库的制作和使用
C语言的函数库是多组经过验证的常用函数的集合,编写C语言程序时使用库函数,既可以提高程序运行效率,又可以提高编程质量,使用方法如#include 和#include。
根据使用库函数时,函数库加载时机的差异,将函数库分为静态函数库和动态函数库,具体差异是:C语言程序如果使用静态函数库的函数,那么整个函数库的代码都会和C语言程序一起编译成可执行代码,程序的体积会膨胀;如果使用动态函数库的函数,则C语言程序只会和函数库文件名以及函数名一起编译成可执行代码(不编译函数代码),运行时去查找函数库文件和函数体,程序的体积基本不变。
简单概括就是,静态函数库是“以空间换时间”,增加程序体积,减少运行时间,如果静态函数库发生改变,则整个程序必须重新编译,因为函数库被整合到了最终可执行代码中;动态函数库则是“以时间换空间”,增加运行时间,减少程序体积,如果动态函数库发生改变,程序无须重新编译,因为函数库没有整合到最终可执行代码中。
Linux中静态函数库表示为”libxxx.a”,windows中后缀名为”.lib”;Linux中动态函数库表示为”libxxx.so”,windows中后缀名为”.dll”。函数库中存放内容包括:(1)函数名称,(2)函数目标代码(二进制),(3)重定位信息(链接需要)等。
1 静态函数库的制作和使用
静态函数库的制作步骤可以用下图来描述,具体包括
(1)编写函数的.c文件(例如add.c、sub.c、mul.c和div.c)
(2)编写Makefile,然后make,实现函数的编译和归档入库
函数的编译:使用gcc –c 只编译不链接函数.c文件,分别生成函数的目标文件(例如add.o、sub.o、mul.o和div.o)。
函数的归档入库:使用ar -rc libxxx.a $(objects) 将目标文件归档入库。
(3)编写头文件(例如ku.h),声明静态函数库中的所有函数,目的是kumain.c函数#include头文件后,可以调用相应的函数,至此,完成函数库的制作。
1.1 静态函数库的制作示例
示例的内容是建立静态函数库libstatic.a,库中包括add、sub、mul和div函数,然后在kumain.c函数中引用这4个函数,实现两个整数的加减乘除,整个文件的结构是
(1) 编写函数的.c文件
编写4个函数文件add.c、sub.c、mul.c和div.c
// add.c float add(int a, int b) { return (a+b); } // sub.c float sub(int a, int b) { return (a-b); } // mul.c float mul(int a, int b) { return (a*b); } // div.c float div(int a, int b) { return (a/b); }
(2)编写头文件
// ku.h float add(int a, int b); float sub(int a, int b); float mul(int a, int b); float div(int a, int b);
(3)编写Makefile
### Makefile for static func lib objects = add.o sub.o mul.o div.o libstatic.a : $(objects) ar -rc libstatic.a $(objects) add.o : add.c gcc -c add.c sub.o : sub.c gcc -c sub.c mul.o : mul.c gcc -c mul.c div.o : div.c gcc -c div.c clean : rm libstatic.a $(objects)
(4)使用make编译.c文件,生成.o文件,归档.o文件到函数库libstatic.a中,完成静态函数库的制作。
1.2 静态函数库的使用
(1)编写kumain.c,调用libstatic.a中的add、sub、mul和div函数
// kumain.c #include <stdio.h> #include "ku.h" int main (void) { int a,b; a = 10; b = 3; printf("a = %d.\nb = %d.\n",a,b); printf("static a+b = %f.\n",add(a,b)); printf("static a-b = %f.\n",sub(a,b)); printf("static a*b = %f.\n",mul(a,b)); printf("static a/b = %f.\n",div(a,b)); return 0; }
(2)使用gcc kumain.c –o kumain.o –L ./ku2 –lstatic 编译kumain.c文件,运行./kumain.o查看运行结果,成功。
1.3 使用nm查看kumain.o中的符号信息
nm命令是列出.o文件,.a文件和.so文件中的符号信息,如符号的值,符号类型及符号名称等。符号通常指定义出的函数,全局变量等。
使用 nm libstatic.a查看符号信息,得到
使用nm kumain.o >label.text查看kumain.o中的符号信息,得到
080484f9 T add 0804a020 B __bss_start 0804a020 b completed.6591 0804a018 D __data_start 0804a018 W data_start t deregister_tm_clones 0804853c T div 080483e0 t __do_global_dtors_aux 08049f0c t __do_global_dtors_aux_fini_array_entry 0804a01c D __dso_handle 08049f14 d _DYNAMIC 0804a020 D _edata 0804a024 B _end 080485c4 T _fini 080485d8 R _fp_hw t frame_dummy 08049f08 t __frame_dummy_init_array_entry 080487b8 r __FRAME_END__ 0804a000 d _GLOBAL_OFFSET_TABLE_ w __gmon_start__ 080482cc T _init 08049f0c t __init_array_end 08049f08 t __init_array_start 080485dc R _IO_stdin_used w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable 08049f10 d __JCR_END__ 08049f10 d __JCR_LIST__ w _Jv_RegisterClasses 080485c0 T __libc_csu_fini T __libc_csu_init U __libc_start_main@@GLIBC_2.0 0804842d T main T mul U printf@@GLIBC_2.0 080483a0 t register_tm_clones T _start 0804850f T sub 0804a020 D __TMC_END__ T __x86.get_pc_thunk.bx
1.4 nm命令简介
nm [option(s)] [file(s)]
有用的options:
-A 在每个符号信息的前面打印所在对象文件名称;
-C 输出demangle过了的符号名称;
-D 打印动态符号;
-l 使用对象文件中的调试信息打印出所在源文件及行号;
-n 按照地址/符号值来排序;
-u 打印出那些未定义的符号;
常见的符号类型
A 该符号的值在今后的链接中将不再改变;
B 该符号放在BSS段中,通常是那些未初始化的全局变量;
D 该符号放在普通的数据段中,通常是那些已经初始化的全局变量;
T 该符号放在代码段中,通常是那些全局非静态函数;
U 该符号未定义过,需要自其他对象文件中链接进来;
W 未明确指定的弱链接符号;同链接的其他对象文件中有它的定义就用上,否则就用一个系统特别指定的默认值。
相关文章
- 这篇文章主要为大家详细介绍了C语言实现放烟花的程序,有音乐播放,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-02-23
- 本篇文章主要介绍C语言中char的知识,并附有代码实例,以便大家在学习的时候更好的理解,有需要的可以看一下...2020-04-25
- 这篇文章主要介绍了详解如何将c语言文件打包成exe可执行程序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-25
- free函数是释放之前某一次malloc函数申请的空间,而且只是释放空间,并不改变指针的值。下面我们就来详细探讨下...2020-04-25
- 这篇文章主要介绍了C语言中计算正弦的相关函数总结,包括正弦和双曲线正弦以及反正弦的函数,需要的朋友可以参考下...2020-04-25
详解C语言中的rename()函数和remove()函数的使用方法
这篇文章主要介绍了详解C语言中的rename()函数和remove()函数的使用方法,是C语言入门学习中的基础知识,需要的朋友可以参考下...2020-04-25- 这篇文章主要介绍了C语言中求和、计算平均值、方差和标准差的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-12-10
- 本篇文章主要讲解C语言 基本语法,这里提供简单的示例和代码来详细讲解C语言的基本语法,开始学习C语言的朋友可以看一下,希望能够给你带来帮助...2021-09-18
- 这篇文章主要介绍了C语言中send()函数和sendto()函数的使用方法,是C语言入门学习中的基础知识,需要的朋友可以参考下...2020-04-25
- 今天小编就为大家分享一篇C语言实现从文件读入一个3*3数组,并计算每行的平均值,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-25
- 这篇文章主要介绍了使用C语言操作文件的基本函数整理,包括创建和打开以及关闭文件的操作方法,需要的朋友可以参考下...2020-04-25
- 这篇文章主要介绍了C语言中memcpy 函数的用法详解的相关资料,需要的朋友可以参考下...2020-04-25
- 这篇文章主要介绍了C语言中查找字符在字符串中出现的位置的方法,分别是strchr()函数和strrchr()函数的使用,需要的朋友可以参考下...2020-04-25
- 很多同学在学习c语言的时候是不是会碰到a++和++a都有甚么作用啊。今天我们就来探讨下...2020-04-25
- 这篇文章主要对C语言中const关键字的用法进行了详细的分析介绍,需要的朋友可以参考下...2020-04-25
- 下面小编就为大家带来一篇C语言实现时间戳转日期的算法(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-04-25
- 这篇文章主要介绍了C语言之整数划分问题(递归法)实例代码的相关资料,需要的朋友可以参考下...2020-04-25
- 本文给大家简单介绍下c实现linux下的数据库备份的方法和具体的源码,十分的实用,有需要的小伙伴可以参考下。...2020-04-25
C语言正则表达式详解 regcomp() regexec() regfree()用法详解
C语言处理正则表达式常用的函数有regcomp()、regexec()、regfree()和regerror(),这里就为大家介绍一下,需要的朋友可以参考一下啊...2020-04-25- 这篇文章主要介绍了c语言实现找最大值最小值位置查找,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-04