在一个文件中,我有这个宏:
#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_BEGIN
和EXTERN_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
宏的需求减少了。