老生常谈C语言静态函数库的制作和使用

 更新时间:2016年08月26日 10:02:06   投稿:jingxian  
下面小编就为大家带来一篇老生常谈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,库中包括addsubmuldiv函数,然后在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/C++中的static与extern关键字的使用详解

    浅谈C/C++中的static与extern关键字的使用详解

    本篇文章是对C/C++中的static与extern关键字的使用进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C++设计模式迪米特法则实例

    C++设计模式迪米特法则实例

    这篇文章主要为大家详细介绍了C++设计模式迪米特法则实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-12-12
  • QString的常用方法(小结)

    QString的常用方法(小结)

    这篇文章主要介绍了QString的常用方法(小结),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • C++中for auto的用法及说明

    C++中for auto的用法及说明

    这篇文章主要介绍了C++中for auto的用法及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Qt重写QComboBox实现下拉展示多列数据

    Qt重写QComboBox实现下拉展示多列数据

    这篇文章主要为大家详细介绍了Qt如何重写QComboBox实现下拉展示多列数据,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-11-11
  • c语言中的移位运算符

    c语言中的移位运算符

    这篇文章主要介绍了c语言中的移位运算符,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • 利用Matlab绘制有趣图像的示例代码

    利用Matlab绘制有趣图像的示例代码

    这篇文章主要为大家总结了一些利用Matlab绘制的有趣好看的图像的示例代码。文中的示例代码简洁易懂,感兴趣的小伙伴可以动手试一试
    2022-03-03
  • opencv检测直线方法之形态学方法

    opencv检测直线方法之形态学方法

    这篇文章主要为大家详细介绍了opencv检测直线方法之形态学方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-12-12
  • 通过c语言调用系统curl动态库的示例详解

    通过c语言调用系统curl动态库的示例详解

    这篇文章中我们将通过一个简单的示例来讲解如何在Ubuntu系统中通过C语言调用动态库(共享库)的方法,我们将使用libcurl库,这是一个基于客户端的URL传输库,广泛用于各种程序和应用中以访问网页和服务器数据,需要的朋友可以参考下
    2024-03-03
  • C语言实现顺序表的顺序查找和折半查找

    C语言实现顺序表的顺序查找和折半查找

    这篇文章主要为大家详细介绍了C语言实现顺序表的顺序查找和折半查找,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-06-06

最新评论