老生常谈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 未明确指定的弱链接符号;同链接的其他对象文件中有它的定义就用上,否则就用一个系统特别指定的默认值。

(0)

相关推荐

  • C++获取本机MAC,IP,MASK地址的方法

    本文实例讲述了C++获取本机MAC,IP,MASK地址的方法,分享给大家供大家参考.具体方法如下: 复制代码 代码如下: #include "InitSock.h"  #include <stdio.h>    #include <iphlpapi.h>  #pragma comment(lib, "IPHLPAPI.lib")    u_char g_ucLocalMac[6];  DWORD g_dwGatewayIP;  DWORD g

  • 如何利用Emacs来调试C++程序

    俗话说,Emacs是神的编辑器,而Vim是编辑器之神.高手程序员都是用这两样神器进行开发.本人觉得,Emacs之所以厉害,是因为许多在其他编辑器下必须用鼠标点选很多步的操作,在Emacs下都可以通过键盘来完成.大大地节省了你在显示器上找按钮的时间.Emacs在Linux上运行感觉比windows流畅些,用Emacs编辑程序时,手基本不用离开键盘,就可以完成所有的工作.那么今天就让我们看看如何利用Emacs来调试C++程序. 一.安装Emacs和GCC 下载地址:Emacs:http://www.

  • Mac下使用Eclipse编译C/C++文件出现 launch failed, binary not found 解决方案

    新建C/C++工程第一页,toolchains选择哪个都一样,如图: 第二步: 而后点击"Advanced settings",出现下图: 将第一项取消,第二项选上,点击 OK. 而后点击下一步,点击结束. 新工程完成后,随便新建一个语法正确的初始 .c 文件,然后 command+b "Build All",根目录下出现Binaries目录,大功告成!

  • C++获得本机所有网卡的IP和MAC地址信息的实现方法

    一台机器上可能不只有一个网卡,但每一个网卡只有一个MAC地址,而每一个网卡可能配置有多个IP地址:如平常的笔记本电脑中,就会有无线网卡和有线网卡(网线接口)两种:因此,如果要获得本机所有网卡的IP和MAC地址信息,则必须顺序获得每个网卡,再依次获取其信息等:在windows sdk中,用IP_ADAPTER_INFO结构体存储网卡信息,包括网卡名.网卡描述.网卡MAC地址.网卡IP等,该结构体的主要描述如下所示: typedef struct _IP_ADAPTER_INFO { struct

  • 解决在Mac下直接解压C++静态库出现的问题

    发现问题 C++的静态库(*.a文件)就是一个压缩包,把所有 *.o 文件打包在里面. 所以我想尝试做的事很简单:就是把静态库里的 *.o 文件都解压出来,然后在用这些 *.o 文件链接合并为一个动态库.我直接双击解压的,这样就得到了一堆的 *.o 文件.然后我执行了生成动态库的命令,类似如下: c++ -g -dynamiclib -Wl,-headerpad_max_install_names -o libtest.dylib /usr/lib/libexpat.dylib /usr/lib

  • 动态库调用静态库示例讲解

    生成动态库: 需要的目标文件得用-fPIC选项生成. 而静态库所需的目标文件可以不用-fPIC选项. 例: 复制代码 代码如下: /////// static.h void static_print(); ///////static.cpp #include <iostream> #include "static.h" void static_print() { std::cout<<"This is static_print function&quo

  • 详解C++的JSON静态链接库JsonCpp的使用方法

    JsonCpp部署方法: 在http://sourceforge.net/projects/jsoncpp/中下载最新版本的jsoncpp库源码. 之后将jsoncpp-src-版本号-tar.gz解压出来,打开makefiles中的jsoncpp.sln进行编译,之后build文件夹下的vs71\debug\lib_json中会有一个.lib静态链接库. JsonCpp主要包含三种类型的class:Value Reader Writer. jsoncpp中所有对象.类名都在namespace

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

    C语言的函数库是多组经过验证的常用函数的集合,编写C语言程序时使用库函数,既可以提高程序运行效率,又可以提高编程质量,使用方法如#include 和#include. 根据使用库函数时,函数库加载时机的差异,将函数库分为静态函数库和动态函数库,具体差异是:C语言程序如果使用静态函数库的函数,那么整个函数库的代码都会和C语言程序一起编译成可执行代码,程序的体积会膨胀:如果使用动态函数库的函数,则C语言程序只会和函数库文件名以及函数名一起编译成可执行代码(不编译函数代码),运行时去查找函数库文件和函

  • 老生常谈C语言动态函数库的制作和使用(推荐)

    >>>>>>老生常谈C语言接静态函数库的制作和使用>>点击进入 2 动态函数库的制作和使用 动态函数库的制作步骤可以用下图来描述,具体包括 (1) 编写函数的.c文件(例如add.c.sub.c.mul.c和div.c) (2) 编写Makefile,然后make,实现函数的编译和归档入库 函数的编译:使用gcc –c add.c -fPIC只编译不链接函数.c文件,分别生成函数的目标文件(例如add.o.sub.o.mul.o和div.o). 函数的归档入

  • 浅谈Linux C语言动态库及静态库

    假设在math目录下已编辑好add.c sub.c div.c mul.c func_point.c文件,func_point.c为包含main()的源文件! 动态库的制作: 方法一: gcc -c -fPIC add.c sub.c div.c mul.c //-c表示生成.o目标文件,-f后加一些编译选项,PIC表示与位置无关 gcc -shared -o libmymath.so add.o sub.o mul.o div.o//创建共享库mymath,添加add.o,sub.o,mul.

  • 易语言图片格式转换器制作方法

    图片格式转换器工具相当的多,实用性也是相当的强,除了软件能够转换,在线也能转换,没有想过自己制作一个这样的软件呢,现在就用易言语来制作一个简单的图片格式转换器,支持批量转换功能.拖入功能! 1.废话不多说了,先来做界面,这里用到通用对话框,拖放对象组件,图片列表采表框,预览图片采用画板,转换进度用了一个进度条,其他就是一些按钮.编辑框.组合框.还有一些标签,不怎么美观,也将就着用! 2.这里为了操作列表框,添加一个菜单,主要是删除列表框的内容,包括全部删除和删除选中,这个菜单就不用显示了,将其设

  • 易语言支持库的安装说明

    警告:为避免支持库在使用过程中发生错误及不稳定情况,请不要反编译,修改及破解支持库文件. 易语言及eyuyan是易语言公司在中国的注册商标. 本说明书中提到的公司名和产品名是相应公司的商标或注册商标. 一.系统要求 IBM PC AT或兼容机 Windows95或更高版本 支持库要求的最低易语言版本 注意:某些支持库必须有其他相应版本的软件支持才能达到预期效果. 二.支持库说明: 注意:所有支持库在发布之前已经过详细的测试,在正常环境下可以稳定使用,如果出现运行错误情况,用户可采用以下措施中的一

  • R语言入门使用RStudio制作包含Rcpp代码的R包

    目录 1. 创建项目 2. 修改一些文件 3. 打包 4. 使用Eigen或其它依赖库会出现的问题 前面博客中有提及,当我们进行模拟想要再次进行提速时,通常都会使用Rcpp将我们的R代码改成C++代码.具体Rcpp的使用可参考博客:Rcpp入门R代码提速方法过程,R语言学习RcppEigen进行矩阵运算. 平时在我们使用的时候,直接使用Rcpp::sourceCpp()就可以直接将我们的C++代码中的函数进行导入,这不会遇到什么问题,但如果我们想要使用snowfall进行并行时就不能再这样做了.

  • Symfony2使用第三方库Upload制作图片上传实例详解

    本文实例分析了Symfony2使用第三方库Upload制作图片上传的方法.分享给大家供大家参考,具体如下: 我们在应用程序或者网站的个人资料里一般都有设置头像的功能,这一章我们在Symfony2里用第三方的一个比较有名Upload库来制作上传图片的功能. 一.安装第三方库 1.在composer.json文件中的"require"中加入 "codeguy/upload": "*" 2.运行指令安装 composer update 二.编码 1.编

  • 易语言支持库简单安装加载添加

    1,首先,准备好欲安装的易语言支持库文件(fne.fnr或lib为后缀名等文件) 2,接下来,有必要对易语言支持库的文件做重要讲解.要安装支持库之前,先要弄明白易语言安装目录下的两个文件夹:lib和static_lib.lib文件夹内存放的以.fne或.fnr等后缀名的支持库文件,这里我们暂且称之为"普通库文件";static_lib文件夹内存放的"静态库文件",支持库文件名中包含"_static"字符且以.lib为后缀名的文件,这种文件可以支持

  • 易语言密码查看功能制作

    易语言密码查看插件制作步骤 1.如你所见  一个编辑框 和一个按钮 2. _按钮1_鼠标左键被按下 _按钮1_鼠标左键被放开 编辑框 输入方式 密码输入 你懂得 3.代码不能少 .版本 2 .程序集 窗口程序集_启动窗口 .子程序 _按钮1_鼠标左键被按下, 逻辑型 .参数 横向位置, 整数型 .参数 纵向位置, 整数型 .参数 功能键状态, 整数型 编辑框1.输入方式 = 0 .子程序 _按钮1_鼠标左键被放开, 逻辑型 .参数 横向位置, 整数型 .参数 纵向位置, 整数型 .参数 功能键状

  • 总结升级易语言支持库保证向下兼容性

    易语言支持库升级之后,要保证向下兼容性,主要是做到以下几点: 一:保证原有的易语言源程序(.e)能正常打开(兼容点1).正常编译(兼容点2).编译结果正确(兼容点3): 二:保证原有的易语言程序(.exe)能正常运行(兼容点4).运行结果正确(兼容点5). 这里说的"原有的易语言源程序"和"原有的易语言程序"是指,替换新版支持库文件之前,使用旧版支持库编写的易语言源程序,和使用该源程序编译生成的可执行程序. 本文主要就此问题结合具体情况进行分析和总结. 一,为支持库

随机推荐