程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 靜態函數庫的制作和使用,靜態函數庫制作

靜態函數庫的制作和使用,靜態函數庫制作

編輯:關於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個函數,實現兩個整數的加減乘除,整個文件的結構是

 

      所有代碼見: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:

  • -A 在每個符號信息的前面打印所在對象文件名稱;
  • -C 輸出demangle過了的符號名稱;
  • -D 打印動態符號;
  • -l 使用對象文件中的調試信息打印出所在源文件及行號;
  • -n 按照地址/符號值來排序;
  • -u 打印出那些未定義的符號;

常見的符號類型

  • A 該符號的值在今後的鏈接中將不再改變;
  • B 該符號放在BSS段中,通常是那些未初始化的全局變量;
  • D 該符號放在普通的數據段中,通常是那些已經初始化的全局變量;
  • T 該符號放在代碼段中,通常是那些全局非靜態函數;
  • U 該符號未定義過,需要自其他對象文件中鏈接進來;
  • W 未明確指定的弱鏈接符號;同鏈接的其他對象文件中有它的定義就用上,否則就用一個系統特別指定的默認值。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved