最可靠方式是按优先级顺序检测预定义宏:先判 _MSC_VER(MSVC 或 clang-cl),再判 __clang__(原生 Clang),最后判 __GNUC__(GCC/MinGW);版本判断须用对应宏区间比较,避免硬匹配或依赖非稳定宏。
直接用预定义宏判断编译器版本最可靠,但必须按优先级顺序检测、用区间比较、避开不稳定宏——否则在 Clang on Windows 或 MinGW 环境下极易误判。
如何正确区分 GCC / Clang / MSVC 编译器类型
不能只靠
或
单独存在来断定编译器:
一旦被定义,就代表当前是 MSVC 或 clang-cl 模式(ABI/头文件兼容),应立即终止后续判断
在 Windows 上常和
同时存在;只有当
未定义而
存在时,才是原生 Clang
仅在前两者都未定义时才可视为 GCC 或 MinGW-GCC
典型误判场景:Clang on Windows 项目里写
,结果跳过 MSVC 兼容路径,导致 STL 行为不一致。
GCC 版本判断:必须用
系列做区间比较
、
、
是 GCC 工具链唯一稳定可用的整数宏,值可安全用于数值比较:
立即学习
“
C++免费学习笔记(深入)
”;
C知道
CSDN推出的一款AI技术问答工具
下载
写
表示支持 GCC 12.x 及以上(含 12.1、12.4)
写
表示 ≥ 11.3
避免硬匹配:
会漏掉 12.1,且无法适配未来补丁更新
别单独依赖
判断 C++ 特性——GCC 10 和 11 对
支持程度不同,建议结合特性宏验证
MSVC 和 Clang 版本判断的关键差异
MSVC 唯一可信宏是
(如 VS2019=1920,VS2022=1930),它在 clang-cl 下也会被定义,这反而是优势:
用
可安全启用 VS2022+ 新增的
constexpr 构造等 STL 特性
绝对不要用
——它含构建号,值跳跃无规律,CI 中易因 Update 版本不同而失效
Clang 应优先用
/
,而非仅靠
(它只是布尔标记,不带版本信息)
Clang on Windows 若启用了
,
值可能被强制设为 201703L,此时不能单靠它推断语言能力
C++ 标准版本宏的跨平台陷阱
在 GCC/Clang 下反映编译选项(如
),但在 MSVC 下默认不更新——需手动开启
或依赖
:
MSVC 推荐统一用
(如
),它比
更可靠
Clang/GCC 下仍以
为准,但要注意:某些旧版 Clang(如 3.5)即使加了
,
仍返回 201103L
混合项目中,若同时检测
和
,务必先判断编译器类型,再选对应宏,否则逻辑错乱
最易忽略的一点:宏值只表示“编译器声称支持的标准”,不代表实际实现了所有特性——比如 GCC 8.2 声称支持 C++17,但
需要额外链接
才能用。真要用某个特性,最好搭配
或
特性宏二次确认。
__GNUC____clang___MSC_VER__clang___MSC_VER_MSC_VER__clang____GNUC__#if defined(__clang__) && !defined(_MSC_VER)__GNUC____GNUC____GNUC_MINOR____GNUC_PATCHLEVEL#if __GNUC__ >= 12#if __GNUC__ > 11 || (__GNUC__ == 11 && __GNUC_MINOR__ >= 3)#if __GNUC__ == 12__GNUC____cpp_concepts_MSC_VER#if _MSC_VER >= 1930std::span_MSC_FULL_VER__clang_major____clang_minor____clang__/Zc:__cplusplus__cplusplus__cplusplus-std=c++17/Zc:__cplusplus_MSVC_LANG_MSVC_LANG#if _MSVC_LANG >= 201703L__cplusplus__cplusplus-std=c++14__cplusplus__cplusplus_MSC_LANGstd::optional-lstdc++fs__has_include__cpp_xxx