原创 静态库的提出过程与使用示例

2011-2-27 21:37 1663 5 5 分类: 软件与OS

       在刚学编程的时候,没有模块化的概念,所有的代码都堆砌在一个main函数里面。而且那个时候有个特点是在写c++小程序时最喜欢cin,cout,在c程序中最钟情的当然是printf,scanf了。完成一个小程序要是不再屏幕上打印点东西就心里不舒服,美其名曰这是与用户交互。随后对游戏编程有了点兴趣,那么就买了本《windows游戏编程大师技巧》,跟着书中的例子做,结果第一个例子输进去后一点buid,天啊,那么多错误,排除掉所有的语法及打字错误后,都归结为“...undefined symbol...",或者"...unresolved external symbol..",这对非科班的刚学编程的我是一件多么大的打击阿,那时寝室同学不学这个,没人交流,寝室没有网络,不方便查,我唯一能做的就是一遍一遍的对代码,期望能发现点什么,结果总是失望告终。最后只好去网吧查,百度之,输入我认为的关键字“windos 游戏编程大师技巧   编译错误...",竟然发现有好多问同样问题的人,所有的答案都是在build选项的库路径里填入一个XXX.lib。这是在学习c++中从未遇到过的操作,顿时觉得好高级,事情解决了后还沾沾自喜,又会了点东西,但又有种惊悚的感觉,计算机的东西我不知道的真的是太多太多了。回首一下,感慨一下,当时的我是多么不知天高地厚,刚接触点c,c++,没有任何操作系统,数据结构知识,就想编出一个带窗口的游戏。而且由于没有人给出意见,弯路走了不少,数据结构,算法的底子没有打就开始接触win32,进而mfc。。一头扎入了个无底洞,兴趣受到极大挫折。

        上面提到的事情其实都跟一个概念有关:库。

         库包括静态链接库,动态链接共享库等等概念,这里把静态库的产生总结以下,并用一个回文数的例子来说明。

         为什么要有库的概念呢?从上面的一些糗事简介,可以总结出以下发展步骤:

(1)只有main函数的时代。没有模块,一个Main函数包办所有的功能。这个阶段是一本c++,c教程学了前几章,尤其是刚学会输入输出的阶段。

(2)用函数实现模块化的时代。此时学会了用函数把一个固定的功能打包,实现复用。但仍然是跟main函数写到一个源文件中。

(3)将函数的实现写到单独的源文件中。在main函数所在的源文件中include,再编译,build.

在第三个步骤中,实际是将函数放到一个单独的可重定位目标模块中,应用程序员可以把模块链接到自己的可执行文件中。

这种方法的优点是将编译器的实现与函数的实现分离开来,并且仍然对程序员保持适度的便利。然而,一个很大的缺点是系统中每个可执行文件都包含这一个函数实现集合的完全拷贝,这对磁盘空间是一种浪费。更糟糕的是,每个可执行的程序都将它自己的这些函数的拷贝放到存储器中,这对存储器又是一个浪费。另一个缺点是,对这个函数实现集合的源文件中的任何函数的修改,都要求将此源文件从新编译。以上种种,使得(3)的方法耗时难以维护。

(4)有没有一种这样的文件呢,在(3)的基础上,链接器只拷贝被程序引用的目标模块,使得可执行文件对磁盘和存储器的浪费降低?

这样,静态库的概念就出来了。

实际上,所有的编译系统都提供一种机制,将所有相关的目标模块打包成一个单独的文件,称为静态库(static library),它也可以作为链接器的输入。当链接器构造一个输出的可执行文件时,它只拷贝静态库里被应用程序引用的目标模块。


下面在linux环境下,用gcc ,ar等工具用一个例子说明这一过程。

我们把一个判断一个整数是否为回文数的函数封装到库里。首先,写出此函数的实现,命名为palindrome.c

/*************palindrome.c**********/

int reverse(int n)
{
    int result;
    int remainder;
    while(n!=0)
    {
        remainder=n%10;
        n/=10;
        result=10*result+remainder;
    }
    return result;
}


int palindrome(int n)
{
    if(n==reverse(n))
        return 1;
    else
        return 0;
}

/**************************************/


下面把这两个函数创建到一个库mylib_math.a中:

gcc -c palindorme.c

ar rcs mylib_math.a  palindrome.o

这样就生成了mylib_math.a库。


下面在main函数中调用该库中的palindrome方法:

/*************************test.c*******************/

#include<stdio.h>
int main()
{
    printf("please input a number:");
    int a;
    scanf("%d",&a);
    if(palindrome(a))
    printf("this number is a palindrome!\n");
    else
    printf("this number is not a palindrome !\n");
}

/*******************************************************/


为了创建这个可执行文件,我们将编译和链接输入文件test.o和 mylib_math.a

gcc -O2 -c test.c

gcc -static -o test test.o  ./mylib_math.a

./test

test可执行文件正确运行。说明库的创建和调用成功。




PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
5
关闭 站长推荐上一条 /3 下一条