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

C项目结构——每个模块的标题与一个大标题

  •  6
  • finnw  · 技术社区  · 16 年前

    在我的编程生涯中,我参与过许多C项目,头文件结构通常属于以下两种模式之一:

    1. 一个包含所有函数原型的头文件
    2. .h 每个文件 .c

    选项2的优点对我来说是显而易见的——它使在多个项目之间共享模块更便宜,并使模块之间的依赖关系更容易看到。

    但是选项1的优点是什么?它必须有一些优势,否则它就不会那么受欢迎。


    放置 #define struct s等也有所不同,但对于这个问题,我想重点讨论功能原型。

    9 回复  |  直到 11 年前
        1
  •  9
  •   unwind    16 年前

    我认为#1的主要动机是。..懒惰。人们认为,将事物拆分为单独的文件会使依赖关系变得更加明显,因此管理依赖关系太难了,和/或认为为所有事物设置单独的文件在某种程度上是“多余的”。

    当然,这也可能是“历史原因”的情况,即程序或项目从小规模发展而来,没有人花时间重构头文件。

        2
  •  5
  •   sharptooth    16 年前

    选项1允许将所有定义放在一个地方,因此您只需包含/搜索一个文件,而不必包含/搜索多个文件。如果你的系统作为库交付给第三方,这个优势就更加明显了——他们不太关心你的库结构,他们只是想能够使用它。

        3
  •  4
  •   freespace    16 年前

    .c 有自己的 .h .h 其中包括所有其他 .h 文件夹。这带来了两全其美的好处,但代价是保持了 .h

    .h 文件,但第三方可以只包括包罗万象的文件 .h

        4
  •  4
  •   Artur Soler    16 年前

    为每个.c使用不同的.h的另一个原因是编译时。如果只有一个.h(或者如果有更多个.h,但你将它们都包含在每个.c文件中),每次在.h文件中进行更改时,你都必须重新编译每个.c文件。在大型项目中,这可能意味着浪费了大量宝贵的时间,也可能破坏您的工作流程。

        5
  •  4
  •   jpinto3912    16 年前
    • 1只是没有必要。我看不出有什么好的理由去做,也有很多理由去避免。

    遵循#2的三条规则,没有问题:

    • #ifndef _HEADER_Namefile
      #define _HEADER_Namefile_
      

        #endif
    

    这将允许您在同一模块上多次包含相同的头文件(可能会无意中发生),而不会引起任何麻烦。

    • 头文件上不能有定义。..这是每个人都认为他/她知道的关于函数原型的事情,但几乎总是忽略全局变量。

      extern unsigned long G_BEER_COUNTER;
      

    它指示编译器G_BEER_COUNTER符号实际上是一个无符号长符号(因此,其工作方式类似于声明),在其他一些模块上,它将具有正确的定义/初始化。(这也允许链接器保留已解析/未解析的符号表。)实际定义(没有extern的同一语句)在module.c文件中。

    • 只有在证明绝对必要的情况下,您才能在头文件中包含其他头文件。include语句应该只在.c文件(模块)上可见。这使您能够更好地解释依赖关系,并发现/解决问题。
        6
  •  4
  •   R.. GitHub STOP HELPING ICE    15 年前

        7
  •  1
  •   Miroslav BajtoÅ¡    16 年前

    当你有一个非常大的项目,有成百上千个小的头文件时,依赖性检查和编译会显著减慢速度,因为必须打开和读取大量的小文件。这个问题通常可以通过使用预编译头来解决。

        8
  •  0
  •   Maggie    16 年前

    在C++中,你肯定希望每个类都有一个头文件,并使用如上所述的预编译头文件。

        9
  •  0
  •   Eugene Bujak    16 年前