无法直接获取完整版本字符串,需用编译器特有宏(如GCC的__GNUC__等、Clang的__clang__等、MSVC的_MSC_VER)手动拼接,且须注意跨编译器兼容性与宏定义差异。
没有标准宏能直接给出“完整版本字符串”,所有可用宏都只提供数字型主/次/补丁号,必须手动拼接;依赖编译器自身定义的宏,跨编译器不可互换。
如何获取 GCC 的主次补丁号(
、
、
)
GCC 用三个独立宏分别表示主版本、次版本和补丁号,例如 GCC 12.3.0 对应
、
、
。注意:
在旧版 GCC(如 4.8 之前)可能未定义,需先检查是否已声明。
实操建议:
始终用
这类守卫判断,而非直接展开
拼接完整版本时,用预处理器字符串化(
)配合
等宏需借助中间宏,否则会直接展开为数字字面量而非字符串
不要尝试用
宏做逻辑判断——它是字符串字面量(如
),无法参与
数值比较
Clang 如何区分它和 GCC(
、
、
、
)
Clang 定义了
为 1,并提供三组数字宏。关键点在于:Clang 会**同时定义**
系列宏(默认兼容 GCC 4.2.1 接口),所以仅靠
无法识别 Clang。必须优先检测
。
立即学习
“
C++免费学习笔记(深入)
”;
常见错误现象:
C知道
CSDN推出的一款AI技术问答工具
下载
代码里写
就进 Clang 分支,导致误判
把
当作 Clang 自身补丁号——其实它对应的是 LLVM 的 patch 版本,和 Clang 发布版号不完全一致(例如 Clang 16.0.0 可能对应
)
忽略
:macOS 上的 Clang(Xcode 自带)还额外定义该宏,值为 Apple 内部构建号(如
),和开源 Clang 无关
MSVC 的版本宏(
)为什么不能直接拆成主次版本?
是一个四位或五位整数,比如 MSVC 19.38 对应
,MSVC 14.35 是
。但它**不是纯数值编码**:19.38 → 1938,但 19.40 → 1940,而 19.41 → 1941 —— 表面上可除 100 取整,但微软从未承诺这种映射稳定。更麻烦的是,MSVC 2022 17.x 开始引入
(如
),其高 4 位是
,后续数字是内部 build 号,无公开语义。
实操建议:
用
判断最低支持,别试图
需要“显示版本”时,硬编码映射表比实时计算更可靠(例如
)
是 C++ 标准语言模式(如
),和编译器版本无关,别混淆
跨编译器统一提取版本字符串的最小可行方案
没有银弹。最简健壮做法是:先确定编译器种类,再用各自数字宏拼接字符串,最后用预处理器字符串化。难点在 Clang 和 GCC 共存时的优先级,以及 MSVC 的非线性编码。
示例片段(可用于头文件):
真正复杂的地方在于:你要用这个版本号做什么。如果只是日志打印,字符串化够用;如果要条件编译某段仅 GCC 13+ 支持的属性(如
),就必须回到数值宏做
判断,且必须查清该特性实际落地的最早版本——文档写的“GCC 13”可能实际从 13.2 才可用。
__GNUC____GNUC_MINOR____GNUC_PATCHLEVEL____GNUC__ == 12__GNUC_MINOR__ == 3__GNUC_PATCHLEVEL__ == 0__GNUC_PATCHLEVEL__#if defined(__GNUC__) && __GNUC__ >= 5#__GNUC____VERSION__"12.3.0"#if__clang____clang_major____clang_minor____clang_patchlevel____clang____GNUC____GNUC____clang__#ifdef __GNUC____clang_patchlevel____clang_patchlevel__ == 6__apple_build_version__14030022_MSC_VER_MSC_VER_MSC_VER == 19381435_MSC_FULL_VER193833135_MSC_VER#if _MSC_VER >= 1930#define MSC_MAJOR (_MSC_VER / 100)1938 → "19.38"_MSVC_LANG202002L#if defined(__clang__)
# define COMPILER_NAME "Clang"
# define COMPILER_VERSION_STR \
# __clang_major__ "." # __clang_minor__ "." # __clang_patchlevel__
#elif defined(__GNUC__)
# define COMPILER_NAME "GCC"
# define COMPILER_VERSION_STR \
# __GNUC__ "." # __GNUC_MINOR__ "." # __GNUC_PATCHLEVEL__
#elif defined(_MSC_VER)
# define COMPILER_NAME "MSVC"
# if _MSC_VER == 1938
# define COMPILER_VERSION_STR "19.38"
# elif _MSC_VER == 1937
# define COMPILER_VERSION_STR "19.37"
# else
# define COMPILER_VERSION_STR "unknown"
# endif
#else
# define COMPILER_NAME "unknown"
# define COMPILER_VERSION_STR "unknown"
#endif[[assume]]#if