代码之家  ›  专栏  ›  技术社区  ›  PeterK

有什么好的理由包括源文件(*.c*.cpp)吗?

  •  1
  • PeterK  · 技术社区  · 15 年前

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

    我的问题是:库的开发人员为什么使用这种方法有充分的理由吗?这种方法非常不受欢迎。(或者至少我一辈子都被告知这是坏的,根据我自己的经验,我相信这是坏的)。或者它只是一个糟糕的设计,而且在这种方法中没有收益?

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

    一个额外的问题:有没有一种方法可以解决这个问题,而不需要太多地触及库代码?我有很多自己的工作,不想再创造更多;)

    6 回复  |  直到 15 年前
        1
  •  3
  •   Roger Pate    15 年前

    据我所见( 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和msv项目 将doublefann.o(来自doublefann.c)与fann.o(来自fann.c)或fixedfann.o(来自fixedfann.c)等链接起来,要么它们的文件被搞砸了,要么类似的东西出了问题。

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

    当你在这里的时候,如果你继续不使用他们的项目设置,你可能会跳过编译fann.c等。可能仅仅从项目中删除这些就足够了——然后它们就不会被编译和链接。你会想选择正确的 要使用的double-/fixed-/floatfann,否则将得到相同的链接错误。(我没有看他们的说明,但是看到这个总结在那里解释得更深入一点也不会感到惊讶。)

        2
  •  2
  •   cHao    15 年前

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

    但是,如果要像这样包含实际代码,它应该 static 在它的大多数声明中,或者它将导致您看到的警告。

        3
  •  0
  •   Borealid    15 年前

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

    如果文件只包含在一个地方,为什么不把它变成一个独立的编译单元(并通过 extern 声明)?为什么还要把它包括在内?

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

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

    这是假设应该内联的函数被标记 inline 你有一个很好的编译器和链接器。

    我不知道怎么快速解决这个问题。

        4
  •  0
  •   Jens Gustedt    15 年前

    我不知道那个图书馆,但正如你所描述的,它要么是不好的实践,要么是你对如何使用它的理解不够好。

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

        5
  •  0
  •   Steven Sudit    15 年前

    我还没有看过代码,但可能包含的.c或.cpp文件实际上包含在头中工作的代码。例如,模板或内联函数。如果是这样的话,那么这些警告将是虚假的。

        6
  •  0
  •   Brian Hooper    15 年前

    我现在在家里做这件事,因为我是Linux上相对C++的新手,不想陷入链接器的困难中。但我不推荐它做适当的工作。

    (我还必须将一个Heal.dAT包含到C++程序中,因为Rational Rose不允许头文件是发布软件的一部分,我们需要运行系统上的特定源文件(出于神秘的原因))。