You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C/C++中空宏定义的作用及LLVM可见性属性相关疑问

关于LLVM中LLVM_EXTERNAL_VISIBILITY宏的疑问

我在LLVM代码库中看到这段代码:

class LLVM_EXTERNAL_VISIBILITY Function : public GlobalObject,
                                          public ilist_node<Function> {

通过clangd查到该宏的定义如下:

/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked
/// into a shared library, then the class should be private to the library and
/// not accessible from outside it.  Can also be used to mark variables and
/// functions, making them private to any shared library they are linked into.
/// On PE/COFF targets, library visibility is the default, so this isn't needed.
///
/// LLVM_EXTERNAL_VISIBILITY - classes, functions, and variables marked with
/// this attribute will be made public and visible outside of any shared library
/// they are linked in to.
#if __has_attribute(visibility) &&                                             \
    (!(defined(_WIN32) || defined(__CYGWIN__)) ||                              \
     (defined(__MINGW32__) && defined(__clang__)))
#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden")))
#if defined(LLVM_BUILD_LLVM_DYLIB) || defined(LLVM_BUILD_SHARED_LIBS)
#define LLVM_EXTERNAL_VISIBILITY __attribute__((visibility("default")))
#else
#define LLVM_EXTERNAL_VISIBILITY     // <-------------- THIS
#endif
#else
#define LLVM_LIBRARY_VISIBILITY
#define LLVM_EXTERNAL_VISIBILITY
#endif

我有两个疑问:

  • 为什么要定义无值的标识符,却像有值一样使用它?我的猜想是它起到条件作用:满足条件时预处理器替换为文本,否则不替换,但避免编译器报未定义标识符的错误,这是否正确?
  • 这里可指定哪些属性?是否与类的链接特性相关?

解答

1. 无值宏的作用

你的猜想完全正确。这是C/C++预处理器的常用技巧:

  • 当满足特定编译条件(比如构建LLVM动态库时),LLVM_EXTERNAL_VISIBILITY会被替换为__attribute__((visibility("default"))),给类/函数加上链接可见性属性;
  • 不满足条件时,宏被定义为空,预处理器会直接移除代码中的LLVM_EXTERNAL_VISIBILITY标记,既不影响代码逻辑,又能避免因宏未定义导致的编译错误。

这种写法让同一份代码能自动适配不同编译配置,无需手动修改属性标记。

2. 属性与链接特性的关系

这里用到的是GCC/Clang的可见性属性,和类、函数的链接特性直接相关:

  • visibility("hidden"):标记的符号(类、函数、变量)仅在当前共享库内部可见,外部无法引用,能缩小动态库的符号表规模,减少符号冲突风险;
  • visibility("default"):标记的符号保持默认的公共可见性,允许外部代码从共享库中引用,这正是LLVM_EXTERNAL_VISIBILITY的核心作用——确保类在动态库构建场景下能被外部访问。

另外,宏定义中的条件判断也考虑了平台差异:Windows(PE/COFF)平台的默认符号可见性规则与类Unix系统不同,因此这些平台下会直接将宏定义为空,无需额外添加属性。


内容的提问来源于stack exchange,提问作者Alessandro Bertulli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 00:20:52