克服大型项目的C限制

克服大型项目的C限制,c,C,C显示其时代的一个方面是代码的封装。许多现代语言都有类、名称空间、包。。。组织代码比简单的“包含”更方便 因为C语言仍然是许多大型项目的主要语言。你如何克服它的局限性 我认为一个主要因素应该是纪律严明。我想知道如何处理大量C代码,您可以推荐哪些作者或书籍。 将代码分成功能单元 将这些代码单元构建到各个库中 在库中使用隐藏符号以减少命名空间冲突 想想开源代码吧。Linux内核、GNUC库、X窗口系统和Gnome桌面项目中有大量的C代码。然而,这一切都是协同工作的。这是因为大多数代码看不到任何其他

C显示其时代的一个方面是代码的封装。许多现代语言都有类、名称空间、包。。。组织代码比简单的“包含”更方便

因为C语言仍然是许多大型项目的主要语言。你如何克服它的局限性

我认为一个主要因素应该是纪律严明。我想知道如何处理大量C代码,您可以推荐哪些作者或书籍。

  • 将代码分成功能单元
  • 将这些代码单元构建到各个库中
  • 在库中使用隐藏符号以减少命名空间冲突

想想开源代码吧。Linux内核、GNUC库、X窗口系统和Gnome桌面项目中有大量的C代码。然而,这一切都是协同工作的。这是因为大多数代码看不到任何其他代码。它只通过定义良好的接口进行通信。在任何大型项目中都要这样做。

实现某种封装的一个好方法是将模块的内部方法或变量声明为
static
,正如Andres所说,
static
是您的朋友。但是说到朋友。。。如果希望能够将库分隔为两个文件,则需要在另一个文件中看到的一个文件中的某些符号不能是静态的。 确定一些命名约定:库
foo
中的所有非静态符号都以
foo\ucode>开头。并确保始终遵循它们:正是这些符号似乎有约束(“我需要称之为
foo_max
?!但它只是
max
!”)才会发生冲突


正如Zan所说,一个典型的Linux发行版可以被看作是一个主要用C语言编写的大型项目。有接口,大型子项目作为单独的过程实现。在单独流程中的实现有助于调试、测试和代码重用,并且除了链接级别上唯一存在的层次结构之外,它还提供了第二个层次结构。当您的项目变得足够大时,将一些功能放在单独的流程中可能就有意义了。一些已经像C编译器那样专业化的东西通常被实现为三个进程:预处理器、编译器、汇编程序。

有些人不喜欢它,但我主张将我的结构和相关函数组织在一起,就像它们是一个显式传递this指针的类一样。例如,结合一致的命名约定使名称空间显式。标题类似于:

typedef struct foo {
  int x;
  double y;
} FOO_T

FOO_T * foo_new();

int foo_set_x(FOO_T * self, int arg1);

int foo_do_bar(FOO_T * self, int arg1);

FOO_T * foo_delete(FOO_T * self);

在实现中,所有“私有”函数都是静态的。这样做的缺点是,您实际上无法强制用户不要去破坏结构的成员。这就是c的生活。但我发现这种风格有利于很好地重用C类型

如果你可以控制项目(例如,内部或你付钱给其他人来做),你可以简单地设置规则,并使用审查和工具来执行它们。语言不需要这样做,例如,您可以要求模块之外可用的所有函数(=一组文件,甚至不需要是单独的)都必须这样标记。实际上,您将迫使开发人员考虑接口并坚持使用它们

如果你真的想说明这一点,你也可以定义宏来显示这一点,例如

#define PUBLIC 
#define PRIVATE static
或者类似的


你说得对,纪律是关键。它包括设置规则并确保遵守规则。

类似的帖子,不是专门针对C的,但包含了很好的一般建议:风格没有问题,但我更喜欢
FOO_*x;x->x=1超过
FOO_T*x;foo_集x(x,1)。对于C程序员来说,这一点要清楚得多。(你可以通过不给
struct
成员定义来强制用户不要去搅乱他们。只需说
typedef struct foo foo_T
,然后他们就可以使用指向你的类型的指针而不看里面。)我同意Chris的观点——要么你为结构提供定义,并期望客户端代码改变其成员,或者使用指向typedef惯用法的指针隐藏内容。大多数OO语言中的公共和私有并不意味着静态和自动。我同意,纪律是重要的,实现纪律的重要步骤是规则,评论和工具如前所述,但我认为重写是很好的,例如在不遵守规则的情况下设置。早期审查(当代码尚未完成时)可以降低因重写而产生的额外成本。重写决定可以由“高层”正式决定,并进一步强调要遵守规则。只要多个文件包含的头中没有使用
PRIVATE
。:-)