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個函數,實現兩個整數的加減乘除,整個文件的結構是
所有代碼見:http://files.cnblogs.com/files/hfxin2001-eric-daddy/ku.rar
(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 08048370 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 08048400 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 08048550 T __libc_csu_init U __libc_start_main@@GLIBC_2.0 0804842d T main 08048527 T mul U printf@@GLIBC_2.0 080483a0 t register_tm_clones 08048330 T _start 0804850f T sub 0804a020 D __TMC_END__ 08048360 T __x86.get_pc_thunk.bx
1.4 nm命令簡介
nm [option(s)] [file(s)]
有用的options:
常見的符號類型