当一个库被连接到目标上时,库中的所有函数是否都会被加到一个.EXE文件中?
不会。当启动连接程序时,它会寻找“未定义的外部函数”,也就是说,它将在每一个库文件中查找源代码文件中未定义的函数。当它找到一个未定义的外部函数后,它会引入包含该函数定义的目标代码。(obj)。不幸的是,如果这个函数是在一个包含其它函数定义的源文件中被编译的话,那么这些函数也会被包含进来,你的可执行代码中将包含一些不需要的代码。因此,将库函数放到各自的源文件中是很重要的——否则会浪费宝贵的程序空间。有些编译程序包含
特殊的“精明的”连接程序,这些连接程序能查出不需要的函数并去掉它们,从而使这些函数不再进入你的程序。
下面举一个例子:假设有两个源文件,分别为libfunc1.c和libfunc2.c,它们所包含的函数都要被放到一个库中。源文件libfunc1.c包含以下两个函数:
void func_one ()
{
...
}
void rune_two()
{
...
}
源文件libfunc2.c包含以下函数:
void func_three()
{
...
}
现在假设已经把这两个源文件编译到一个名为myfuncs.1ib的库中。如果一个与myfuncs.lib连接的程序要调用func_one()函数,连接程序就会在myfuncs.lib库中寻找包含func_one()函数定义的目标代码,并且把它连接进来。不幸的是,函数func_one()是在包含func_two()函数定义的同一个源文件中被编译的,因此,即使你的程序不会用到func_two(),连接程序也不得不把它连接进来。当然,这里假设func_one()中并没有包含对func_two()的调用。如果一个程序包含一个对func_three()的调用,那么只有func_othree()的目标代码会被连接进来,因为该函数是在它自己的源文件中被编译的。
一般说来,你应该尽量把库函数放到各自的源文件中。这种组织方式有助于提高程序的效率,因为程序只会和那些真正需要的函数进行连接,而不会和那些不需要的函数进行连接。这种组织方式在小组开发的情况下也是很有帮助的;在小组开发中,源文件的上交和发放非常频繁,如果一个程序员要对一个包含在其自身的源文件中的函数进行维护,那么他可以集中维护这个函数;如果这个函数所在的源文件中还包含其它一些需要维护的函数,那么这些函数就无法发放给其它小组成员,因为它们包含在一个源文件中。
特殊的“精明的”连接程序,这些连接程序能查出不需要的函数并去掉它们,从而使这些函数不再进入你的程序。
下面举一个例子:假设有两个源文件,分别为libfunc1.c和libfunc2.c,它们所包含的函数都要被放到一个库中。源文件libfunc1.c包含以下两个函数:
void func_one ()
{
...
}
void rune_two()
{
...
}
源文件libfunc2.c包含以下函数:
void func_three()
{
...
}
现在假设已经把这两个源文件编译到一个名为myfuncs.1ib的库中。如果一个与myfuncs.lib连接的程序要调用func_one()函数,连接程序就会在myfuncs.lib库中寻找包含func_one()函数定义的目标代码,并且把它连接进来。不幸的是,函数func_one()是在包含func_two()函数定义的同一个源文件中被编译的,因此,即使你的程序不会用到func_two(),连接程序也不得不把它连接进来。当然,这里假设func_one()中并没有包含对func_two()的调用。如果一个程序包含一个对func_three()的调用,那么只有func_othree()的目标代码会被连接进来,因为该函数是在它自己的源文件中被编译的。
一般说来,你应该尽量把库函数放到各自的源文件中。这种组织方式有助于提高程序的效率,因为程序只会和那些真正需要的函数进行连接,而不会和那些不需要的函数进行连接。这种组织方式在小组开发的情况下也是很有帮助的;在小组开发中,源文件的上交和发放非常频繁,如果一个程序员要对一个包含在其自身的源文件中的函数进行维护,那么他可以集中维护这个函数;如果这个函数所在的源文件中还包含其它一些需要维护的函数,那么这些函数就无法发放给其它小组成员,因为它们包含在一个源文件中。