头文件中的函数应该声明为“extern”吗?

54

函数在头文件中应该被声明为 extern 吗?还是它们默认就是 extern

例如,我应该这样写吗:

// birthdays.h
struct person find_birthday(const char* name);

或者是这个:

// birthdays.h
extern struct person find_birthday(const char* name);

1
一个比下面的回答更易理解的答案在https://dev59.com/8mMl5IYBdhLWcg3wuY_K#18173554,"extern applied to functions"部分。 - Luca Ceresoli
6个回答

23

来自C语言书籍

如果声明包含extern存储类别说明符,或者是没有存储类别说明符的函数的声明(或两者都有),那么:

  • 如果已经存在一个具有文件作用域的可见标识符声明,则结果链接与可见声明的链接相同;
  • 否则结果为外部链接。

因此,如果这是翻译单元中唯一的声明,则它将具有外部链接。


23
有点混乱。 - Geremia
1
因此,如果您首先在标头文件中将函数声明为“static”,然后在同一文件下方放置另一个“extern”声明,则将忽略后一个声明。否则省略指定将隐式使其为“extern”。但是,在标头文件中对于变量使用extern非常重要,因此有时人们更喜欢明确地始终使用extern(即使省略函数会暗示相同的链接)。 - Lou

21

它们是用 "extern" 隐式声明的。


变量也一样吗? - Aravind
2
@Aravind - 不,变量不会隐式声明为extern;您必须在变量声明前显式添加extern。正如我在我的答案中所指出的,我更喜欢在函数声明前加上extern,以保持与少数全局变量声明的对称性,但编译器在函数声明前不需要extern,许多人更喜欢在函数声明中省略它。函数定义可以通过复合语句或函数体(用{...}括起来)而不是在函数签名后加分号来识别。 - Jonathan Leffler

20

头文件中声明的函数通常是(除非你非常努力)extern。个人而言,我更喜欢在那里看到显式的关键字 - 但编译器不需要它。这提醒读者它们是extern,由于人类比计算机更容易出错,我发现这个提醒有所帮助。

对于变量,使用extern关键字(没有初始化程序)在头文件中很重要。因此,为了与头文件中声明的(非常少的)全局变量对称,我也使用extern来定义函数 - 即使这不是绝对必要的。


4
我也加上了明确的 extern;头文件中的声明要么是函数的 externstatic inline,变量的则是 externstatic const,其他很少需要。 - Christoph

16

不,头文件中声明的函数不需要声明为extern

但是在头文件中定义并且被多个.c文件 #include后的变量需要声明为extern


2
我从不在我的源代码中使用"extern",但有些人会这样做。在我看来,在变量前加上extern而不是函数可以更明显地显示哪些是函数和哪些是变量(可能包括函数指针)。我认为很多情况可能取决于.h文件中的声明如何创建以及它们与主要的.c文件的关系。我通常先输入.h文件的原型,然后复制/粘贴到.c文件中并添加函数体(删除原型末尾的分号),因此在复制/粘贴后需要将"extern"添加到头文件中或从主.c文件中删除。

"extern" 在需要在多个源文件(模块)之间直接共享全局变量时是必需的。当然,您可以通过使用访问函数来避免这种情况,但这会带来一些成本。 - Kostas

0
“在头文件中,函数应该被声明为extern吗?还是默认就是extern的呢?”
“在头文件中,函数应该被声明为extern吗?”
- 这是一个观点问题,甚至在开源社区中也存在不同意见。
我之所以这样做很简单。如果不在头文件中声明,你可以在使用它的文件中,在使用之前将该函数声明为extern。 如果将其放在头文件中,那么在使用该函数的文件中会包含这个头文件。
从这个角度来看,我认为在头文件中加上extern更正确。 然而,编译器故意这样做是因为曾经有些糟糕的程序员不知道更好的做法。
“或者默认情况下它们就是extern的呢?”
- 函数声明默认情况下隐式地是extern的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接