在C++跨平台开发中,不同编译器对C++标准的支持程度、特性实现细节存在差异,准确识别当前编译器的完整版本号是做特性适配、兼容处理的基础。各大编译器厂商都提供了专属的预定义宏,我们可以通过这些宏的判定和取值提取,自动化识别当前编译环境。

主流编译器的版本识别宏说明
不同编译器提供的预定义宏命名规则不同,我们可以通过先判定编译器厂商宏,再提取对应版本宏的方式获取完整版本信息,以下是常见编译器的核心识别宏:
- GCC编译器:通过
__GNUC__判定是否为GCC,版本信息由__GNUC__(主版本)、__GNUC_MINOR__(次版本)、__GNUC_PATCHLEVEL__(补丁版本)三个宏共同组成。 - Clang编译器:通过
__clang__判定是否为Clang,版本信息由__clang_major__(主版本)、__clang_minor__(次版本)、__clang_patchlevel__(补丁版本)组成。 - MSVC编译器:通过
_MSC_VER判定是否为MSVC,该宏直接表示编译器的主版本号,_MSC_FULL_VER可以获取更完整的版本编码。 - Intel编译器:通过
__INTEL_COMPILER判定,该宏的取值包含主版本、次版本信息,__INTEL_COMPILER_UPDATE表示补丁版本。
自动化识别编译器的完整实现代码
我们可以编写一个通用的检测函数,依次判定不同编译器的特征宏,最终输出编译器的名称和完整版本号,代码如下:
#include <iostream>
#include <string>
#include <sstream>
// 获取编译器名称和完整版本号
std::string get_compiler_info() {
std::ostringstream oss;
// 判定Clang编译器
#if defined(__clang__)
oss << "Clang编译器, 版本号: "
<< __clang_major__ << "."
<< __clang_minor__ << "."
<< __clang_patchlevel__;
// 判定GCC编译器
#elif defined(__GNUC__)
oss << "GCC编译器, 版本号: "
<< __GNUC__ << "."
<< __GNUC_MINOR__ << "."
<< __GNUC_PATCHLEVEL__;
// 判定MSVC编译器
#elif defined(_MSC_VER)
oss << "MSVC编译器, 主版本号: " << _MSC_VER;
// 提取完整版本号,_MSC_FULL_VER格式为MMNNNNNNN,前两位是主版本,中间两位是次版本,后五位是补丁版本
int full_ver = _MSC_FULL_VER;
int major = full_ver / 10000000;
int minor = (full_ver % 10000000) / 100000;
int patch = full_ver % 100000;
oss << ", 完整版本号: " << major << "." << minor << "." << patch;
// 判定Intel编译器
#elif defined(__INTEL_COMPILER)
oss << "Intel编译器, 版本号: "
<< __INTEL_COMPILER << "."
<< __INTEL_COMPILER_UPDATE;
// 未知编译器
#else
oss << "未知编译器";
#endif
return oss.str();
}
int main() {
std::cout << get_compiler_info() << std::endl;
return 0;
}
上述代码通过条件编译依次检测不同编译器的特征宏,优先检测Clang是因为Clang在某些情况下也会定义__GNUC__宏,避免误判。编译运行后,会根据当前使用的编译器输出对应的版本信息。
编译器版本宏对照表
以下是主流编译器的识别宏和版本取值规则的完整对照表,方便开发时快速查阅:
| 编译器名称 | 厂商判定宏 | 主版本宏 | 次版本宏 | 补丁版本宏 | 版本格式说明 |
|---|---|---|---|---|---|
| GCC | __GNUC__ | __GNUC__ | __GNUC_MINOR__ | __GNUC_PATCHLEVEL__ | 主版本.次版本.补丁版本 |
| Clang | __clang__ | __clang_major__ | __clang_minor__ | __clang_patchlevel__ | 主版本.次版本.补丁版本 |
| MSVC | _MSC_VER | _MSC_VER(主版本编码) | _MSC_FULL_VER提取 | _MSC_FULL_VER提取 | _MSC_VER为简化版本,_MSC_FULL_VER可提取完整版本 |
| Intel C++ Compiler | __INTEL_COMPILER | __INTEL_COMPILER(包含主次版本) | 无单独宏 | __INTEL_COMPILER_UPDATE | __INTEL_COMPILER.补丁版本 |
| IBM XL C++ | __xlC__ | __xlC__ | 无单独宏 | 无单独宏 | __xlC__取值为版本编码 |
注意事项
在使用这些预定义宏时需要注意,部分宏是编译器特有的,不属于C++标准范畴,因此不同编译器之间的宏没有统一的命名规则。另外,Clang为了兼容GCC,会同时定义__GNUC__相关宏,因此检测顺序上需要把Clang的判定放在GCC之前,避免错误识别为GCC编译器。如果需要在代码中根据版本号做特性适配,可以在条件编译中直接判定对应宏的取值,比如判定GCC版本是否大于等于9:
#if defined(__GNUC__) && __GNUC__ >= 9 // GCC 9及以上版本支持的特性代码 #endif