很显然tlink并不是上面资料里所说的“精明的”连接程序,它会将和源代码中未定义函数一起编译的所有函数都载入exe文件中,所以f3会被载入b.exe中。
那么我们的问题就很好解决了,我们可以将f1、f2函数写在一个程序里编译成obj文件,将f3写在一个程序里编译成obj文件,再将这两个文件加入cs.lib中,然后进行下面的连接,b.exe文件中就不会出现f3函数的代码了。实验结果发现,原来紧跟在f2的代码后面的f3的代码现在没有了:
所以其实是我之前的思路重点错了,只觉得函数f1、f2、f3都在cs.lib里面不管怎么放都是一样的,但是其实它们编译的方法不同,在cs.lib里面存放的位置或机制也应该不同,我们思考时,应该更加全面地想问题。
用下面的函数替换cs.lib里的printf函数:
将函数编译成obj文件,再用如下语句替换:
这样再使用printf函数就会输出“Do you want to use printf?No printf here.”
如下图程序:
在正常情况下应该输出3,但是用更改后的cs.lib连接后,输出结果如下:
这时printf函数是一个不接受参数、只输出固定语句的函数。
2、拓展研究1、我们在本章研究里是把要添加的obj文件插入cs.lib中再连接,那么能否自己建立lib库,并使tcc编译时对它进行连接呢?
2、我们知道cs.lib里在被连接时是将源文件中未被定义的函数及其一起编译的函数全部加入生成的exe文件中,那么cs.lib里的其他文件是怎么编译的?都是单独编译的吗?
3、Printf和put函数有什么区别?
4、obj文件给出的是偏移地址,exe文件给出了段地址和偏移地址?
5、include头文件在预编译过程中把其他文件合成一个文件。尝试#include<f.c>也是可以正确运行的,看汇编代码这种和加入cs.lib有什么不一样。
6、加入obj文件后之后cs.lib的大小减小了,这是为什么?
3、研究总结本章研究了obj文件的连接问题,掌握了将obj文件加入cs.lib从而连接进文件的方法,熟悉了tlib.exe的基本用法。