Clean C++: 正確使用extern "C"的姿勢

extern "C"用于明確告訴C++編譯器放棄名字粉碎的工作機制,使其保留原始的符號名稱。

純粹的C庫

即使你提供的是一個純粹的C庫,也必須正確使用extern "C",因為你的C函數(shù)可能被C++的程序所使用。

// oss/include/oss_memery.h
#ifndef HF0916DFB_1CD1_4811_B82B_9B8EB1A007D8
#define HF0916DFB_1CD1_4811_B82B_9B8EB1A007D8

#include "oss_common.h"

#ifdef  __cplusplus
extern "C" {
#endif

void* oss_alloc(size_t);
void  oss_free(void*);

#ifdef  __cplusplus
}
#endif

#endif

如果在C庫中遺漏extern "C"的聲明,則C++程序員為了引用該庫的符號時,唯一的選擇就是使用extern "C"包含整個頭文件,而這種模式恰好是一種反模式。因此,C程序員定義對外公開的頭文件時,需要特別的注意這件事情。

#ifdef  __cplusplus
extern "C" {
#endif

#include "oss_memory.h"

#ifdef  __cplusplus
}
#endif

反模式

extern "C"中包含頭文件,是一種典型的反模式。如下示例代碼,oss_common.h置于extern "C"之中,將導(dǎo)致其內(nèi)部或間接通過#include引入的符號都置于extern "C"的作用域之內(nèi);更為嚴重的是,如果oss_common.h也使用了extern "C",將導(dǎo)致嵌套的extern "C"語句,導(dǎo)致混亂的符號聲明。

// oss/include/oss_memery.h
#ifndef HF0916DFB_1CD1_4811_B82B_9B8EB1A007D8
#define HF0916DFB_1CD1_4811_B82B_9B8EB1A007D8

#ifdef  __cplusplus
extern "C" {
#endif

#include "oss_common.h"

void* oss_alloc(size_t);
void  oss_free(void*);

#ifdef  __cplusplus
}
#endif

#endif

實用宏

可以定義一組實用宏,簡化extern "C"的作用域定義。在代碼的可讀性沒有下降的前提下,代碼從6行減少至2行。

// cub/base/externc.h
#ifdef __cplusplus
# define EXTERN_STDC_BEGIN extern "C" {
# define EXTERN_STDC_END }
#else
# define EXTERN_STDC_BEGIN
# define EXTERN_STDC_END
#endif

例如,上例使用宏定義后的代碼如下所示。

// oss/include/oss_memery.h
#ifndef HF0916DFB_1CD1_4811_B82B_9B8EB1A007D8
#define HF0916DFB_1CD1_4811_B82B_9B8EB1A007D8

#include "cub/base/externc.h"
#include "oss_common.h"

EXTERN_STDC_BEGIN

void* oss_alloc(size_t);
void  oss_free(void*);

EXTERN_STDC_END

#endif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容