C与C ++中的外部函数

时间:2012-07-29 20:34:45

标签: c++ c

*.h库的C头文件中,应该声明函数

extern void f();

// or only 

void f();
  1. 仅在C
  2. 中使用时
  3. C++使用时。

5 个答案:

答案 0 :(得分:47)

在C语言或C ++中声明函数时,几乎不需要使用关键字extern。在C和C ++中,默认情况下所有函数都有外部链接。使用extern在头文件中声明函数的奇怪习惯可能具有一些历史根源,但几十年来它已完全无关紧要。

C中有一个[模糊?]异常,它可能与您所询问的内容没有直接关系:在C语言(C99)中,如果在某个翻译单元中,函数被定义为inline并且还声明为extern(使用显式extern),然后该函数的内联定义也用作外部定义。如果翻译单元中不存在带有显式extern的声明,则内联定义仅用作“内部”定义。

P.S。在C ++中有extern "C"这样的东西,但这是完全不同的事情。

答案 1 :(得分:21)

  

在C库的头文件中,应该声明一个函数:

extern void f();
// or only
void f();

问题1:语义

在C ++程序中,函数被声明为函数,不返回值并且不带参数。

在C程序中,函数被声明为函数,不返回任何值,并且采用不确定但不是可变长度的参数列表。

要在C中获得“无参数”含义,请使用以下方法之一:

extern void f(void);
void f(void);

相同的表示法在C ++中也意味着相同的东西,但对于纯C ++代码,在参数列表中使用void不是惯用的(不要在纯C ++代码中这样做)。

问题2:C和C ++之间的互通

Tricky,但通常的规则是你应该将C ++代码的函数声明为extern "C"。要为两者使用相同的源代码,您需要测试__cplusplus宏。你通常会这样做:

#ifdef __cplusplus
#define EXTERN_C       extern "C"
#define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END   }
#else
#define EXTERN_C       /* Nothing */
#define EXTERN_C_BEGIN /* Nothing */
#define EXTERN_C_END   /* Nothing */
#endif

EXTERN_C void f(void);

EXTERN_C_BEGIN
    void f(void);
    int  g(int);
EXTERN_C_END

选项和变体是多方面的,但C和C ++都可以使用标题。

宏通常会在一个通用的头文件中定义,该头文件在任何地方都使用,然后特定的头文件将确保包含通用头文件,然后使用适当的宏形式。

问题3:样式

正式地,在函数声明之前不需要extern表示法。但是,我在头文件中使用它来强调它是一个外部定义函数的声明,以及在标题中声明了全局变量的那些(罕见)场合的对称性。

人们可以而且确实不同意这一点;我遵守当地的规则 - 但是当我是规则制定者时,extern包含在标题中。

答案 2 :(得分:5)

一般用途声明为

#ifdef __cplusplus
extern "C" {
#endif
  void f(void);
#ifdef __cplusplus
}
#endif

否则,extern已过时。

答案 3 :(得分:1)

后者非常好,因为它只是一个功能定义,它告诉那些包括这个标题的人:'这个原型的功能在这附近的某个地方'

在这种情况下,功能与变量明显不同,但这是另一回事。 但请确保您没有包含功能正文,除非您声明它是内联的'或作为类定义(C ++)的一部分或作为模板函数' (也是C ++)。

答案 4 :(得分:1)

在函数原型中指定extern没有任何效果,因为默认情况下它是假定的。每当编译器看到原型时,它就会假定函数是在其他地方定义的(在当前或另一个转换单元中)。这适用于两种语言。

以下主题一般有关于extern的一些有用的评论。

Effects of the extern keyword on C functions