2013-02-08 41 views
3

根据checkpatch.pl脚本“extern声明在.c文件之外” (用于检查补丁是否符合编码风格) 注意:这个在没有编译警告的情况下工作得很好 该问题可以通过在.h文件中放置extern声明来解决。extern声明为什么要在.c文件之外(按照linux编码风格)

a.c 
----- 
int x; 
... 

b.c 
---- 
extern int x; 

==> checkpatch抱怨

a.h 
----- 
extern int x; 

a.c 
---- 
int x; 

b.c 
---- 
#include "a.h" 

==>不抱怨

我想知道为什么这是更好的

我的猜测。 理想情况下,代码被分割成文件以模块化代码(每个文件都是模块) 模块导出的接口放置在头文件中,以便其他模块(或.c文件)可以包含它们。所以如果任何模块想要在外部公开一些变量,那么必须在对应于该模块的头文件中添加一个extern声明。

同样,具有与每个模块(.c文件)相对应的头文件似乎对许多头文件具有 。

+0

这不是那么多,因为头中的接口的实现可能会跨多个翻译单元进行拆分。 – StoryTeller 2013-02-08 11:46:44

+0

*“我的Sepulation”*是正确的。而已。 – 2013-02-08 12:13:02

回答

3

将a.h包含在a.c文件中会更好。这样编译器就可以验证声明和定义是否相互匹配。

a.h 
----- 
extern int x; 

a.c 
---- 
#include "a.h" <<--- add this 
int x; 

b.c 
---- 
#include "a.h" 

该规则的原因是,正如你所假设的那样,我们应该使用编译器来检查我们正在做什么。细节更好。

如果我们允许在所有地方进行外部声明,如果我们想要将x更改为某种其他类型,我们会遇到麻烦。我们必须扫描多少个.c文件才能找到所有的extern int x?许多。如果我们这样做,我们也可能会发现一些extern char x错误。哎呀!

只要在头文件中有一个声明,并在需要的地方包含它,为我们节省了很多麻烦。在任何实际项目中,x不会是头文件中唯一的元素,因此您不会保存文件数量。

0

我总是在.h中放置extern声明的一个原因是为了防止代码复制,特别是如果使用“a.c”代码存在或可能存在更多位代码并且必须访问“x”。在这种情况下,所有文件都必须具有extern声明。

另一个原因是extern声明是模块的接口的一部分,因此我会将它与头文件中的任何其他接口信息一起保存。

0

您的猜测是正确的:为了最大化代码重用和一致性,(公共)声明必须放入头文件中。

同样,拥有与每个模块(.c文件)相对应的头文件似乎与许多头文件一样。

然后习惯它。这是一个合乎逻辑的概念,并且是一个很好的练习,可以使用

0

你有权理解extern声明为什么必须放在头文件中。所以,他们可以轻松地跨不同翻译单位访问。

此外,每个.c文件都没有必要具有相应的.h文件。一个.h文件可以对应于相当数量的.c文件,具体取决于您的模块隔离设计。

1

我看到两个方面的原因:

  1. 如果您共享变量,这是因为它不是在自己的文件,所以你想清楚地表明它是通过将extern到一个头文件共享 - 这方式,只有一个地方[包含目录]来搜索extern声明。
  2. 它避免了某人作出extern声明,然后其他人对同一事物做出不同的(如使用不同类型或属性)extern声明。至少如果它在[相关的]头文件中,则所有文件都使用相同的声明。
  3. 如果您决定更改类型,则只有两个地方需要更改。如果您要添加也使用相同变量的“cc”文件,然后确定int不够好,我需要long,您必须修改所有三个位置,而不是像原来那样修改两个位置每个“ac”,“bc”和“cc”中都包含一个头文件。

拥有一个模块的头文件绝对不是一个坏主意。但它当然可以接受,具体取决于将extern放入某个现有头文件的情况。

另一种方法是使用extern,这通常是比使用extern更好的选择,它有一个getter function,它为您提取变量。这样,变量可以在其自己的源文件中是静态的[不包含“命名空间污染”,并且变量的类型也更加明确 - 编译器可以检测到您是否尝试错误地使用它。

编辑:我应该指出,Linux编码风格是它出于“良好”原因的方式,但这并不意味着不属于Linux源代码的代码不能破坏这些规则。各种方式。我当然不会使用Linux的格式编写我自己的代码 - 我喜欢在单个语句周围额外使用{ },并且我(几乎)总是将{放在一个新的行上,符合大括号所属的任何内容,以及}同一列再次。

0

再一次,有一个头文件对应于每个模块(.c文件)似乎要很多头文件。

正如您所说的,头文件的想法很简单。它们包含模块想要导出(可用)到其他模块(包含在其他.c文件中)的公共接口。这可以包括结构和类型以及函数声明。现在,如果一个模块定义了一个想要提供给其他模块的变量,那么将它包含在头文件中的其他公共部分中是有意义的。这就是为什么extern以头文件结尾的原因。它们只是模块想要公开的东西的一部分。然后任何人都可以通过简单的包含头文件来包含这个公共接口。

每个.c文件有.h文件可能看起来很多,但它可能是正确的做法。但请记住,模块可以在多个.c文件中实现其代码,并选择将其聚合公共接口导出到一个.h文件中。所以,对一件事情来说这不是一件严格的事情。真正的抽象是由模块提供的公共接口。

相关问题