用C 语言编程时,通常要建立一些用户函数。如果这些函数具有通用性,一般的方法是将它们作成头文件,当需要时用“#include”命令将其包含到源程序之中,以提高编程效率。但在特定的程序中一般仅使用这些函数的一部分,若用上述方法包含所有函数,编译器在编译的时候会把所有包含进的函数都进行编译,这无疑会使源程序变得庞大而难于理解,并会影响执行效率。建立用户目标模块库(lib文件)可以解决这个问题,你可以事先把有特定功能的通用的子函数集编译完成后生成的obj文件打入lib文件,当链接器tlink.exe在进行链接操作时,便只会把程序内部用到的通用函数所在的obj文件链接进来(已验证:不能定位到具体函数),这样生成的obj文件便会更精简,生成的exe文件也更小。
(1)用tcc将下面的程序编译成为.obj文件
int f(void){return 1;}
用tcc –c 文件名命令只编译成.obj文件
(2)用c:\c\tcc a.c的方法将编译连接下面的程序。
main(){f();}
显示信息:Undefined symbol '_f' in module a.c
(3)tc2.0提供了一个工具tlib.exe,可以用tlib.exe将一个.obj文件中的代码加到一个.lib文件中。
找到tlib.exe,研究它的使用方法,将(1)中生成的.obj文件加入到c:\c\cs.lib中。
通过tlib命令把pro.obj添加到库文件(*.lib)cs.lib中,
tlib cs.lib + goodluck.obj, cs.lst,运行后用edit命令查看cs.lst中的内容,查找pro40,看是否已添加成功。经查找确定,此文件已成功添加。 │
PRINTF size = 25
_printf
PRO size = 6
_f
PSBP size = 37
PSBP@
上面的工作完成之后,用c:\c\tcc a.c的方法将a.c编译连接成a.exe文件。用debug加载a.exe文件,可以找到main函数和f函数。
a.c中并没有函数f,a.exe中的函数f的代码是在什么时候加入的?:
编译阶段时只是将a.c编译成为obj文件,而且f函数的obj文件在cs.obj中,与cs.obj发生联系只在链接阶段, f函数的代码是在连接阶段加入的
(4)将下面的程序编译成f.obj,将f.obj加入c:\c\cs.lib中。
程序f.c
int f1(int a,int b){ int c; c=a+b;return c;}
int f2(){ int c; c=a-b; return c;}
int f3(){ return a+b+1;}
将下面的程序编译连接为b.exe.用debug加载b.exe,找到其中所有函数代码。
程序b.c
int func(int,int);
int a,b;
main()
{a=f1(1,2);b=f2(20,10);a=func(a,b);printf("%d\n",a);}
int func(int a,int b){return a*b;}
1.程序b.c中并没有写f1、f2和printf函数,b.exe中这些函数的代码是什么时候加入的?:链接时加入的
2.b.exe中有f3的代码吗?:将文件编译连接成为.asm文件,可以看出程序中并没有调用f3的代码,但是通过跟踪代码可以发现,在运行过程中为f3函数分配了空间。
(5)用tlib.exe将cs.lib中的printf函数的代码变为下面的程序的代码:
printf(){puts("Do you want to use printf?No printf here.");}
使得调用printf的用户程序,比如:
main(){int a,b;a=1;b=2;printf("%d",a+b); }
在tcc编译连接后,运行打印出“Do you want to use printf?No printf here.”
加入cs.lib的原理同上,你会发现常用的printf函数出现不同了哦。