在一个文件中,我有这个宏:

#if defined(__cplusplus)
    #define EXTERN_C extern "C"
#else
    #define EXTERN_C extern
#endif

但是,在网络上搜索时,此类宏在C路径(though some examples exist)上具有extern似乎并不常见。它们generally come in pairs更类似于EXTERN_C_BEGINEXTERN_C_END来包装一组声明...并且在C版本中是空操作。

但这意味着在头文件中,您不得不编写:
EXTERN_C_BEGIN
extern int x; /* ...but I already said extern... */
void doSomething(int y);
EXTERN_C_END

发生这种情况是因为extern "C" int x;等效于extern "C" { extern int x; } ...而不是extern "C" { int x; }。后一种形式仅给出“C链接”,而没有给出C外部的历史含义。然后,如果您尝试使C中的单行形式衰减为extern,则不能说EXTERN_C extern int x;,编译器会在C++生成中抱怨“一次两个externs”。

由于没有开始/结束形式,因此(通常)意味着更多的键入。但是,即使在C情况下,我也更喜欢“意向声明”而不是编译器:
EXTERN_C int x;
EXTERN_C void doSomething(int y); /* does `extern` help the C case? */

我似乎不能立即创建一个好的方案,在函数声明中使用extern有助于捕获C中的一个错误。但是从直观上看,冗余似乎有值(value),而且正如我所说,必须执行extern "C",然后仍然放置事情上的extern感觉很尴尬。

偏爱(或避免)两种方法的原因是什么?

最佳答案

通常,您会在为C编写的 header 中看到此内容,并随后使其与C++兼容。最简单的方法是将整个 header 包装在extern "C" {}中。这样一来,无需触摸每个声明,并且主要内容可以保持纯C。

您正在谈论的宏简化了这种包装。现在只有两行:

EXTERN_C_BEGIN
EXTERN_C_END

您不必执行稍微复杂的操作,而是必须隐藏C编译器中的代码行:
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif

另一个问题是全局变量相对较少(与函数相比),并且函数声明中不需要extern。因此,对extern宏的需求减少了。

10-07 13:18
查看更多