在另一个包含一个C源文件?
在另一个.c文件中包含.c文件是否正确(甚至是推荐/好的做法)? 当他们被包含在一个项目文件中会发生什么?
正确使用,这可能是一个有用的技术。
假设你有一个复杂的,性能关键的子系统,只有一个相当小的公共接口和许多不可重用的实现代码。 代码运行到几千行,一百个左右的私人function和相当多的私人数据。 如果你使用非平凡的embedded式系统,你可能经常处理这种情况。
您的解决scheme可能会分层,模块化和解耦,通过在不同的文件中对子系统的不同部分进行编码,可以有效地表示和强化这些方面。
用C,这样做可能会损失很多。 几乎所有的工具链都为单个编译单元提供了不错的优化,但对于任何声明为extern的东西都是非常悲观的。
如果你把所有东西都放到一个C源代码模块中,
-
性能和代码大小的改进 – 在许多情况下函数调用将被内联。 即使没有内联,编译器也有机会生成更高效的代码。
-
链接级别的数据和function隐藏。
-
避免命名空间污染及其必然结果 – 您可以使用较不笨重的名称。
-
更快的编译和链接。
但是当编辑这个文件时,你也会得到一个邪恶的混乱,并且你失去了隐含的模块性。 这可以通过将源文件拆分成多个文件并将其包括在内以产生单个编译单元来克服。
你需要强加一些约定来妥善pipe理这个。 这些将取决于你的工具链在某种程度上,但一些普遍的指针是 –
-
把公共接口放在一个单独的头文件中 – 无论如何你都应该这样做。
-
有一个主要的.c文件,其中包括所有的子公司.c文件。 这也可以包括公共接口的代码。
-
使用编译器保护来确保私有头文件和源模块不被外部编译单元包含。
-
所有的私人数据和function应声明为静态的。
-
保持.c和.h文件之间的概念区别。 这利用了现有的惯例。 不同之处在于你的头文件中会有很多的静态声明。
-
如果你的工具链没有强加任何理由,将私有实现文件命名为.c和.h。 如果你使用include guard,这些将不会产生任何代码,并且不会引入新的名字(在链接过程中你可能会得到一些空的段)。 其他的工具(如IDE)将会对这些文件进行适当的处理。
可以吗? 是的,它会编译
这是推荐? no – .c文件编译为.obj文件,这些文件在编译之后(通过链接器)链接到可执行文件(或库)中,因此不需要在另一个文件中包含一个.c文件。 你可能想要做的是做一个.h文件,列出在其他.c文件中可用的函数/variables,并包含.h文件
没有。
根据您的构build环境(您没有指定),您可能会发现它的工作方式完全符合您的需要。
但是,有许多环境(包括IDE和许多手工制作的Makefiles)需要编译* .c – 如果发生这种情况,由于重复的符号,最终可能会出现链接器错误。
通常应该避免这种做法。
如果你绝对必须#include源文件(通常应该避免),为文件使用不同的文件后缀。
我以为我会分享我的团队决定包括.c文件的情况。 我们的archicture主要由通过消息系统解耦的模块组成。 这些消息处理程序是公共的,并且调用许多本地静态工作函数来完成它们的工作。 当试图获得我们的unit testing用例的覆盖率时,问题就出现了,因为执行这个私有实现代码的唯一方法是间接地通过公共消息接口。 随着一些工人的function在膝盖深处,这变成了一个恶梦,以达到适当的覆盖面。
包括.c文件给了我们一个方法来达到我们在testing中感兴趣的机器上的齿轮。
文件的扩展名对大多数C编译器无关紧要,所以它可以工作。
但是,根据您的makefile或项目设置,包含的c文件可能会生成一个单独的目标文件。 链接时可能会导致双重定义的符号。
您可以在linux中使用gcc编译器将一个输出中的两个c文件链接起来。 假设你有两个c文件,一个是'main.c',另一个是'support.c'。 所以连接这两个的命令是
gcc main.c support.c -o main.out
通过这两个文件将链接到一个单一的输出main.out运行输出的命令将是
./main.out
如果你在support.c文件中声明的main.c中使用了函数,那么你应该使用extern存储类声明它在main中。
C语言不禁止那种#include,但是由此产生的翻译单元仍然必须是有效的C.
我不知道您使用.prj文件的程序。 如果您使用的是“make”或Visual Studio之类的东西,只要确保您设置了要编译的文件列表,而不需要单独编译的文件。
您可以正确地将.C或.CPP文件包括到其他源文件中。 根据您的IDE,通常可以通过查看要包含的源文件属性来防止双连接,通常通过右键单击并单击属性,并取消选中/检查编译/链接/排除构build或任何选项也许。 或者你不能在项目本身包含文件,因此IDE不会知道它存在,不会尝试编译它。 而使用makefiles你只是不会把它的文件编译和链接。
编辑:对不起,我做了一个答案,而不是答复到其他答案:(
将C文件包含到另一个文件是合法的,但不是明智的做法,除非你确切知道你为什么要这样做,你想达到什么目的。
我几乎可以肯定的是,如果你将在这里发布背后的理由,社区将会find另一种更合适的方式来实现你的目标(请注意“几乎”,因为这可能是给定的上下文的解决scheme)。
顺便说一下,我错过了问题的第二部分。 如果C文件被包含到另一个文件中,并且在同一时间包含到项目中,那么为什么链接这些对象可能会出现重复符号问题,即同一个函数将被定义两次(除非它们全部是静态的)。
你应该像这样添加标题
#include <another.c>
注意:这两个文件应该放在同一个地方