0

我一直想知道编译超过 1000 行代码的项目的最佳方法。我只是有一些关于编译项目的最佳方式的基本问题。我正在使用 GCC,如果它有所作为的话。我的问题是:

  • 在多个源文件中包含一个库是否会导致函数被复制两次?

我的意思是,如果我有两个这样的文件:

源代码

#include<stdio.h>
...
void static test_func( ){ printf( "Hey!" ); }

Source2.c

#include<stdio.h>
...
void static test_func( ){ printf( "Hey!" ); }

函数 printf 是否被复制到可执行文件中两次?我想我想避免这种情况,因为很多时候我会有多个共享相同头文件的源文件,我想知道这是否是一种不好的做法。

有一次,我只是通过使用这个来包含其他源文件:

来源.c

#include<stdio.h>
#include "source2.c"

但我不确定这是否也是一种不好的做法。这让我想到了另一个问题:

  • 包含源文件是一种不好的做法吗?

注意:通过不良做法,我的意思是如果某些事情违反惯例或导致某种低效率。

编辑:我刚刚读到这些库是在文件之间共享的。我来宾,这意味着我的第一个问题的答案是否定的。但是,我很好奇,是否使用预处理器包含源文件是一种常见的做法。

4

3 回答 3

1

请注意,库头文件之类的stdio.h仅包含函数的声明printf;它们不包含这些功能的实际代码。像这样的函数的实际代码printf是在链接时添加的,此时所有目标文件和相关库组合在一起形成最终的可执行文件。

包括您的示例中的源文件通常被认为是不好的做法,尽管它可能有特定的用例;我只是想不出有什么好的。您会面临更大的重复定义错误风险,并且最终会不必要地重新构建代码。编译器可能会限制一次可以消化多少代码;包含包含源文件的源文件包含源文件可能会导致构建时间极长或更糟。已经有一段时间了,但我已经看到编译器在非常大的文件上窒息,尤其是在您尝试优化输出时。

将代码拆分为多个源文件的好处在于,如果我只更改一个文件中的某些内容,我(通常)不必重新构建整个项目(当然,这取决于更改的内容);我只需要重新编译那个文件并重新链接。

于 2013-04-25T21:16:06.590 回答
1

在静态链接期间,库函数仅包含一次。如果库是动态的,则根本不添加任何副本,仅添加动态链接信息。

包含.c文件很奇怪,除非您有特定的理由这样做。一个这样的原因是外部模块测试程序,您根本不需要main模块中的功能,但同时为了正确测试它,main需要访问所有无法访问的文件静态数据被不同的文件访问。

于 2013-04-25T19:56:59.440 回答
1

跨文件多次包含库不会使其在最终可执行文件中多次包含

链接器负责解析函数,当它发现它已经知道该函数并且已经包含它时,它不会尝试在静态链接中再次包含它。链接器还将确保它只包含包含的必要文件静态链接中的特定定义。

在动态链接中,链接器会将应用程序在运行时需要的动态库文件加载到内存中

于 2013-04-25T19:57:12.620 回答