#include source(* .c * .cpp)文件有什么好的理由吗?

时间:2010-07-12 09:00:17

标签: c include code-organization

我已经使用开源库(“fast artificial neural network”)工作了一段时间。我在我的静态库中使用它的源代码。然而,当我编译它时,我得到数百个链接器警告,这可能是由于该库在其他* .c文件中包含它的* .c文件这一事实(因为我只包括我需要的一些头文件而且我没有触摸lib本身的代码)。

我的问题:图书馆的开发人员是否有充分的理由使用这种方法,这是强烈劝阻的? (至少我一生都被告知这很糟糕,根据我自己的经验,我认为这很糟糕)。或者这只是糟糕的设计而且这种方法没有收获?

我知道this related question,但它没有回答我的问题。我正在寻找可能证明这一点的理由。

一个额外的问题:如果不过多地触及库代码,有没有办法解决这个问题?我有很多自己的工作,不想创造更多;)

6 个答案:

答案 0 :(得分:3)

据我所知(grep '#include .*\.c'),他们只在doublefann.c,fixedfann.c和floatfann.c中执行此操作,并且每次都包含原因:

/* Easy way to allow for build of multiple binaries */

这种用于简单复制粘贴的预处理器的确切用法确实是包含实现(* .c)文件的唯一有效用途,并且相对较少。 (如果你想为了另一个原因包含一些代码,只需给它一个不同的名称,比如* .h或* .inc。)另一种方法是在给编译器的宏中指定配置(例如-DFANN_DOUBLE,-DFANN_FIXED,或者-DFANN_FLOAT),但他们没有使用这种方法。 (每种方法都有缺点,所以我不是说它们一定是错的,我必须深入研究这个项目才能确定。)

它们提供的makefile和MSVS项目应该已经链接doublefann.o(来自doublefann.c)与fann.o(来自fann.c)或fixedfann.o(来自fixedfann.c)等等,或者他们的文件搞砸了或类似的东西出了问题。

您是否尝试从头开始创建项目(或使用现有项目)并将所有文件添加到其中?如果您这样做,那么正在发生的事情是每个实现文件都是独立编译的,并且生成的目标文件包含冲突的定义。这是处理实现文件的标准方法,许多工具都假定它。唯一可行的解​​决方案是修复项目设置,以便不将这些设置链接在一起。 (好吧,你也可以彻底改变他们的来源,但这不是一个真正的解决方案。)

当你在这里时,如果你继续不使用他们的项目设置,你可能会跳过编译fann.c,et。人。并且可能只是从项目中删除它们就足够了 - 然后它们就不会被编译和链接。你需要选择 one 的double- / fixed- / floatfann来使用,否则你会得到相同的链接错误。 (我没有看过他们的指示,但是看到这个摘要在那里进行了更深入的解释并不会感到惊讶。)

答案 1 :(得分:2)

包含C / C ++代码会导致所有代码在一个翻译单元中粘在​​一起。有了一个好的编译器,这可以带来巨大的速度提升(因为内容可以被内联并且函数调用被优化掉)。

如果要包含这样的实际代码,它的大多数声明都应该有static,否则会导致你看到警告。

答案 2 :(得分:0)

如果您在该.c文件中声明了单个全局变量或函数,则它不能包含在两个编译为相同二进制文件的位置,否则这两个定义将发生冲突。如果它甚至被包含在一个地方,它也不能自己编译,同时仍然被链接到与其用户相同的二进制文件。

如果文件只包含在一个地方,为什么不把它作为一个离散的编译单元(并通过extern声明使用它的全局变量)?为什么要把它包括在内呢?

如果你的C文件没有声明全局变量或函数,它们就是头文件,应该这样命名。

因此,通过详尽的搜索,我可以说,只有在构建多个不同的二进制文件时使用相同的C代码时,可能想要包含C文件的唯一时间。即使在那里,你也在增加编译时间而没有真正的收获。

这假设应该内联的函数标记为inline,并且您有一个不错的编译器和链接器。

我不知道如何快速解决这个问题。

答案 3 :(得分:0)

我不知道那个库,但正如你所描述的那样,这或者是不好的做法,或者你对如何使用它的理解还不够好。

希望被其他人包含的C项目应始终为其他人提供结构良好的.h文件,然后为编译的库提供链接。如果要在头文件中包含函数定义,则应将其标记为static(旧式)或inline(可能自C99起)。

答案 4 :(得分:0)

我没有查看代码,但是包含的.c或.cpp文件实际上可能包含在标头中工作的代码。例如,模板或内联函数。如果是这种情况,则警告将是虚假的。

答案 5 :(得分:0)

我现在正在家里这样做,因为我是Linux上相对较新的C ++新手,并且不想陷入链接器的困难。但我不建议你做正确的工作。

(我曾经不得不将header.dat包含在C ++程序中,因为Rational Rose不允许标题成为已发布软件的一部分,我们需要在运行的系统上使用该特定源文件(出于神秘的原因) 。)