预定义宏

Microsoft C/C++ 编译器 (MSVC) 根据语言(C 或 C++)、编译目标和所选编译器选项预定义某些预处理器宏。

MSVC 支持 ANSI/ISO C99、C11 和 C17 标准以及 ISO C++14、C++17 和 C++20 标准要求的预定义预处理器宏。 该实现还支持多个 Microsoft 专用预处理器宏。

部分宏仅针对特定生成环境或编译器选项定义。 除非另行说明,否则这些宏的定义范围适用于整个翻译单元,就像将它们指定为 编译器选项参数一样/D。 定义后,预处理器会在编译之前扩展宏的指定值。 预定义宏不带参数,不能重新定义。

标准预定义标识符

编译器支持 ISO C99 和 ISO C++11 指定的以下预定义标识符。

  • __func__:封闭函数(用作 char 的函数局部 static const 数组)的未限定、未修饰名称

    void example(){
        printf("%s\n", __func__);
    } // prints "example"
    

标准预定义宏

编译器支持 ISO C99、C11、C17 和 ISO C++17 标准指定的以下预定义宏:

  • __cplusplus:当翻译单元编译为 C++ 时,定义为整数文本值。 其他情况下则不定义。

  • __DATE__:当前源文件的编译日期。 日期是 Mmm dd yyyy 格式的恒定长度字符串文本。 月份名 Mmm 与 C 运行时库 (CRT) asctime 函数生成的缩写月份名相同。 如果值小于 10,则日期 dd 的第一个字符为空格。 任何情况下都会定义此宏。

  • __FILE__:当前源文件的名称。 __FILE__ 展开为字符型字符串文本。 要确保显示文件的完整路径,请使用 (诊断中源代码文件的完整路径)/FC。 任何情况下都会定义此宏。

  • __LINE__:定义为当前源文件中的整数行号。 可使用 #line 指令来更改此宏的值。 __LINE__ 值的整型类型因上下文而异。 任何情况下都会定义此宏。

  • __STDC__:仅在编译为 C,并且指定了 /Za 编译器选项时,定义为 1。 从 Visual Studio 2022 17.2 版本开始,当编译为 C 并指定 /std:c11/std:c17 编译器选项时,它定义为 1。 其他情况下则不定义。

  • __STDC_HOSTED__:如果实现是托管实现并且支持整个必需的标准库,则定义为 1。 其他情况下则定义为 0。

  • __STDC_NO_ATOMICS__ 如果实现不支持可选的标准原子,则定义为 1。 当编译为 C 且指定 /std C11 或 C17 选项之一时,MSVC 实现会将其定义为 1。

  • __STDC_NO_COMPLEX__ 如果实现不支持可选的标准复数,则定义为 1。 当编译为 C 且指定 /std C11 或 C17 选项之一时,MSVC 实现会将其定义为 1。

  • __STDC_NO_THREADS__ 如果实现不支持可选的标准线程,则定义为 1。 当编译为 C 且指定 /std C11 或 C17 选项之一时,MSVC 实现会将其定义为 1。

  • __STDC_NO_VLA__ 如果实现不支持可选的可变长度数组,则定义为 1。 当编译为 C 且指定 /std C11 或 C17 选项之一时,MSVC 实现会将其定义为 1。

  • __STDC_VERSION__ 当编译为 C 且指定 /std C11 或 C17 选项之一时定义。 对于 /std:c11,它扩展到 201112L;对于 /std:c17,则扩展到 201710L

  • __STDCPP_DEFAULT_NEW_ALIGNMENT__ 当指定 /std:c17 或更高版本时,此宏会扩展为 size_t 字面量,该字面量的对齐值由对非对齐感知的 operator new 的调用所保证。 较大的对齐值传递到对齐感知重载,例如 operator new(std::size_t, std::align_val_t)。 有关详细信息,请参阅 /Zc:alignedNew(C++17 过度对齐的分配)

  • __STDCPP_THREADS__:当且仅当程序可以有多个执行线程并编译为 C++ 时,定义为 1。 其他情况下则不定义。

  • __TIME__:预处理翻译单元的翻译时间。 时间是 hh:mm:ss 格式的字符型字符串文本,与 CRT asctime 函数返回的时间相同。 任何情况下都会定义此宏。

Microsoft 专用预定义宏

MSVC 支持其他预定义宏:

  • __ATOM__ 当设置了 编译器选项,并且编译器目标为 x86 或 x64 时,定义为 1/favor:ATOM。 其他情况下则不定义。

  • __AVX__:当设置了 /arch:AVX/arch:AVX2/arch:AVX512 编译器选项,并且编译器目标为 x86 或 x64 时,定义为 1。 其他情况下则不定义。

  • __AVX2__:当设置了 /arch:AVX2/arch:AVX512 编译器选项,并且编译器目标为 x86 或 x64 时,定义为 1。 其他情况下则不定义。

  • __AVX512BW__ 当设置了 编译器选项,并且编译器目标为 x86 或 x64 时,定义为 1/arch:AVX512。 其他情况下则不定义。

  • __AVX512CD__ 当设置了 编译器选项,并且编译器目标为 x86 或 x64 时,定义为 1/arch:AVX512。 其他情况下则不定义。

  • __AVX512DQ__ 当设置了 编译器选项,并且编译器目标为 x86 或 x64 时,定义为 1/arch:AVX512。 其他情况下则不定义。

  • __AVX512F__ 当设置了 编译器选项,并且编译器目标为 x86 或 x64 时,定义为 1/arch:AVX512。 其他情况下则不定义。

  • __AVX512VL__ 当设置了 编译器选项,并且编译器目标为 x86 或 x64 时,定义为 1/arch:AVX512。 其他情况下则不定义。

  • _CHAR_UNSIGNED:如果默认 类型为无符号,则定义为 1char。 当设置了 (默认 char 类型为无符号)编译器选项时,会定义此值/J。 其他情况下则不定义。

  • __CLR_VER:定义为整数文本,表示用于编译应用的公共语言运行时 (CLR) 的版本。 此值按 Mmmbbbbb 格式编码,其中 M 为运行时的主版本,mm 为运行时的次版本,bbbbb 为生成号。 如果设置了 编译器选项,则定义 __CLR_VER/clr。 其他情况下则不定义。

    // clr_ver.cpp
    // compile with: /clr
    using namespace System;
    int main() {
       Console::WriteLine(__CLR_VER);
    }
    
  • _CONTROL_FLOW_GUARD:如果设置了 (启用控制流防护)编译器选项,则定义为 1/guard:cf。 其他情况下则不定义。

  • __COUNTER__:展开为从 0 开始的整数文本。 每次在源文件或源文件的 included 头中使用时,此值都会递增 1。 当使用预编译头时,__COUNTER__ 会记住其状态。 任何情况下都会定义此宏。

    此示例使用 __COUNTER__ 来将唯一标识符分配到同一类型的三个不同对象。 exampleClass 构造函数采用整数作为参数。 在 main 中,应用程序声明类型为 exampleClass 的三个对象,并将 __COUNTER__ 用作唯一标识符参数:

    // macro__COUNTER__.cpp
    // Demonstration of __COUNTER__, assigns unique identifiers to
    // different objects of the same type.
    // Compile by using: cl /EHsc /W4 macro__COUNTER__.cpp
    #include <stdio.h>
    
    class exampleClass {
        int m_nID;
    public:
        // initialize object with a read-only unique ID
        exampleClass(int nID) : m_nID(nID) {}
        int GetID(void) { return m_nID; }
    };
    
    int main()
    {
        // __COUNTER__ is initially defined as 0
        exampleClass e1(__COUNTER__);
    
        // On the second reference, __COUNTER__ is now defined as 1
        exampleClass e2(__COUNTER__);
    
        // __COUNTER__ is now defined as 2
        exampleClass e3(__COUNTER__);
    
        printf("e1 ID: %i\n", e1.GetID());
        printf("e2 ID: %i\n", e2.GetID());
        printf("e3 ID: %i\n", e3.GetID());
    
        // Output
        // ------------------------------
        // e1 ID: 0
        // e2 ID: 1
        // e3 ID: 2
    
        return 0;
    }
    
  • __cplusplus_cli:当编译为 C++ 并设置了 编译器选项时,定义为整数文本值 200406/clr。 其他情况下则不定义。 定义后,__cplusplus_cli 的效力范围是整个翻译单元。

    // cplusplus_cli.cpp
    // compile by using /clr
    #include "stdio.h"
    int main() {
       #ifdef __cplusplus_cli
          printf("%d\n", __cplusplus_cli);
       #else
          printf("not defined\n");
       #endif
    }
    
  • __cplusplus_winrt:当编译为 C++ 并设置了(Windows 运行时编译)编译器选项时,定义为整数文本值 201009/ZW。 其他情况下则不定义。

  • _CPPRTTI:如果设置了 (启用运行时类型信息)编译器选项,则定义为 1/GR。 其他情况下则不定义。

  • _CPPUNWIND:如果设置了一个或多个 /GX(启用异常处理)/clr(公共语言运行时编译)/EH(异常处理模型)编译器选项,则定义为 1。 其他情况下则不定义。

  • _DEBUG:当设置了 /LDd/MDd/MTd 编译器选项时,定义为 1。 其他情况下则不定义。

  • _DLL:当设置了 /MD/MDd(多线程 DLL)编译器选项时,定义为 1。 其他情况下则不定义。

  • __FUNCDNAME__:定义为包含封闭函数修饰名的字符串文本。 此宏仅在函数中定义。 如果使用 /EP/P 编译器选项,则不会展开 __FUNCDNAME__ 宏。

    此示例使用 __FUNCDNAME____FUNCSIG____FUNCTION__ 宏来显示函数信息。

    // Demonstrates functionality of __FUNCTION__, __FUNCDNAME__, and __FUNCSIG__ macros
    void exampleFunction()
    {
        printf("Function name: %s\n", __FUNCTION__);
        printf("Decorated function name: %s\n", __FUNCDNAME__);
        printf("Function signature: %s\n", __FUNCSIG__);
    
        // Sample Output
        // -------------------------------------------------
        // Function name: exampleFunction
        // Decorated function name: ?exampleFunction@@YAXXZ
        // Function signature: void __cdecl exampleFunction(void)
    }
    
  • __FUNCSIG__:定义为包含封闭函数签名的字符串文本。 此宏仅在函数中定义。 如果使用 /EP/P 编译器选项,则不会展开 __FUNCSIG__ 宏。 当针对 64 位目标进行编译时,调用约定默认为 __cdecl。 有关用法的示例,请参阅 __FUNCDNAME__ 宏。

  • __FUNCTION__:定义为包含封闭函数未修饰名的字符串文本。 此宏仅在函数中定义。 如果使用 /EP/P 编译器选项,则不会展开 __FUNCTION__ 宏。 有关用法的示例,请参阅 __FUNCDNAME__ 宏。

  • _INTEGRAL_MAX_BITS:定义为整数文本值 64,表示非矢量整型类型的最大大小(位)。 任何情况下都会定义此宏。

    // integral_max_bits.cpp
    #include <stdio.h>
    int main() {
        printf("%d\n", _INTEGRAL_MAX_BITS);
    }
    
  • __INTELLISENSE__:当在 Visual Studio IDE 中传递 IntelliSense 编译器时,定义为 1。 其他情况下则不定义。 可使用此宏来保护 IntelliSense 编译器不理解的代码,也可使用它在生成和 IntelliSense 编译器之间进行切换。 有关详细信息,请参阅 IntelliSense 缓慢疑难解答提示

  • _ISO_VOLATILE:如果设置了 /volatile:iso 编译器选项,则定义为 1。 其他情况下则不定义。

  • _KERNEL_MODE:如果设置了 (创建内核模式二进制)编译器选项,则定义为 1/kernel。 其他情况下则不定义。

  • _M_AMD64 为面向 x64 处理器或 ARM64EC 的编译定义为整数文本值 100。 其他情况下则不定义。

  • _M_ARM:为面向 ARM 处理器的编译定义为整数文本值 7。 未对 ARM64、ARM64EC 和其他目标定义。

  • _M_ARM_ARMV7VE:如果为面向 ARM 处理器的编译设置了 编译器选项,则定义为 1/arch:ARMv7VE。 其他情况下则不定义。

  • _M_ARM_FP:定义为整数文本值,表示为面向 ARM 处理器的编译设置的 编译器选项/arch。 其他情况下则不定义。

    • 如果未指定 ARM 选项,则该值在 30-39 范围内,表示为 ARM 设置了默认体系结构 (VFPv3)/arch

    • 如果设置了 ,则该值在 40-49 范围内/arch:VFPv4

    • 有关详细信息,请参阅 (ARM)/arch

  • _M_ARM64 为面向 ARM64 的编译定义为 1。 其他情况下则不定义。

  • _M_ARM64EC 为面向 ARM64EC 的编译定义为 1. 其他情况下则不定义。

  • _M_CEE:如果设置了任何 (公共语言运行时编译)编译器选项,则定义为 001/clr。 其他情况下则不定义。

  • _M_CEE_PURE:从 Visual Studio 2015 开始弃用。 如果设置了 /clr:pure 编译器选项,则定义为 001。 其他情况下则不定义。

  • _M_CEE_SAFE:从 Visual Studio 2015 开始弃用。 如果设置了 /clr:safe 编译器选项,则定义为 001。 其他情况下则不定义。

  • _M_FP_CONTRACT 从 Visual Studio 2022 开始起推出。 如果设置了 /fp:contract/fp:fast 编译器选项,则定义为 1。 其他情况下则不定义。

  • _M_FP_EXCEPT:如果设置了 /fp:except/fp:strict 编译器选项,则定义为 1。 其他情况下则不定义。

  • _M_FP_FAST:如果设置了 /fp:fast 编译器选项,则定义为 1。 其他情况下则不定义。

  • _M_FP_PRECISE:如果设置了 /fp:precise 编译器选项,则定义为 1。 其他情况下则不定义。

  • _M_FP_STRICT:如果设置了 /fp:strict 编译器选项,则定义为 1。 其他情况下则不定义。

  • _M_IX86:为面向 x86 处理器的编译定义为整数文本值 600。 对于面向 x64 或 ARM 处理器的编译,则不定义此宏。

  • _M_IX86_FP:定义为表示设置了 /arch 编译器选项的整数文本值或默认值。 只要编译目标为 x86 处理器,就会定义此宏。 其他情况下则不定义。 定义后:

    • 如果设置了 /arch:IA32 编译器选项,则值为 0。

    • 如果设置了 /arch:SSE 编译器选项,则值为 1。

    • 如果设置了 /arch:SSE2/arch:AVX/arch:AVX2/arch:AVX512 编译器选项,则值为 2。 如果未指定 /arch 编译器选项,则为默认值。 当指定了 /arch:AVX 时,还会定义宏 __AVX__。 当指定了 /arch:AVX2 时,还会定义 __AVX____AVX2__。 当指定了 /arch:AVX512 时,还会定义 __AVX____AVX2____AVX512BW____AVX512CD____AVX512DQ____AVX512F____AVX512VL__

    • 有关详细信息,请参阅 (x86)/arch

  • _M_X64 为面向 x64 处理器或 ARM64EC 的编译定义为整数文本值 100。 其他情况下则不定义。

  • _MANAGED:当设置了 /clr 编译器选项时,定义为 1。 其他情况下则不定义。

  • _MSC_BUILD:定义为包含编译器版本号修订号元素的整数文本。 修订号是用句点分隔的版本号的最后一个元素。 例如,如果 Microsoft C/C++ 编译器的版本号为 15.00.20706.01,则 _MSC_BUILD 宏为 1。 任何情况下都会定义此宏。

  • _MSC_EXTENSIONS:如果设置了默认 (启用语言扩展)编译器选项,则定义为 1/Ze。 其他情况下则不定义。

  • _MSC_FULL_VER:定义为编码编译器版本号的主版本号、次版本号和生成号元素的整数文本。 主版本号是用句点分隔的版本号的第一个元素,次版本号是第二个元素,而生成号是第三个元素。

    例如,如果 Microsoft C/C++ 编译器版本为 19.39.33519,则 _MSC_FULL_VER 为 193933519。 在命令行中键入 cl /?,查看编译器的版本号。 任何情况下都会定义此宏。 有关编译器版本控制的详细信息,请参阅 C++ 编译器版本控制,特别是从 Visual Studio 2017 开始的服务版本,它提供了有关 Visual Studio 2019 16.8、16.9、16.10 和 16.11 的详细信息,需要用 _MSC_FULL_VER 将它们区分开来。

  • _MSC_VER:定义为编码编译器版本号的主版本号和次版本号元素的整数文本。 主版本号是用句点分隔的版本号的第一个元素,而次版本号是第二个元素。 例如,如果 Microsoft C/C++ 编译器的版本号为 17.00.51106.1,则 _MSC_VER 的值为 1700。 在命令行中键入 cl /?,查看编译器的版本号。 任何情况下都会定义此宏。

    要在给定的 Visual Studio 版本或更高版本中测试编译器版本或更新,请使用 >= 运算符。 可在条件指令中使用它来比较 _MSC_VER 与已知版本。 如果要比较多个互相排斥的版本,请按版本号的降序顺序进行比较。 例如,此代码将检查 Visual Studio 2017 和更高版本中发布的编译器。 接下来,它会检查 Visual Studio 2015 以及之后发布的编译器。 然后,它会检查 Visual Studio 2015 之前发布的所有编译器:

    #if _MSC_VER >= 1910
    // . . .
    #elif _MSC_VER >= 1900
    // . . .
    #else
    // . . .
    #endif
    

    有关 Visual Studio 2019 16.8 和 16.9 以及 16.10 和 16.11 的详细信息(它们共享相同的主版本和次要版本,因此具有相同的 _MSC_VER 值),请参阅从 Visual Studio 2017 开始的服务版本

    有关编译器版本控制历史、编译器版本号及其对应的 Visual Studio 版本的详细信息,请参阅 C++ 编译器版本控制。 另请参阅 Microsoft C++ 团队博客的 Visual C++ 编译器版本

  • _MSVC_LANG:定义为指定编译器面向的 C++ 语言标准的整数文本。 此宏仅在编译为 C++ 的代码中设置。 默认情况下,或者当指定了 /std:c++14 编译器选项时,此宏为整数文本值 201402L。 如果指定了 /std:c++17 编译器选项,则此宏设置为 201703L。 如果指定了 /std:c++20 编译器选项,则此宏设置为 202002L。 当指定了 /std:c++latest 选项时,它设置为更高的未指定值。 其他情况下则不会定义此宏。 从 Visual Studio 2015 Update 3 开始,提供 _MSVC_LANG 宏和 /std(指定语言标准版本)编译器选项。

  • __MSVC_RUNTIME_CHECKS:当设置了其中一个 /RTC 编译器选项时,定义为 1。 其他情况下则不定义。

  • _MSVC_TRADITIONAL

    • 从 Visual Studio 2017 版本 15.8 开始可用:在设置预处理器一致性模式 /experimental:preprocessor 编译器选项时,定义为 0。 默认情况下,或者当设置了 /experimental:preprocessor- 编译器选项时,定义为 1,指示正在使用传统预处理器。
    • 从 Visual Studio 2019 版本 16.5 开始可用:在设置预处理器一致性模式 /Zc:preprocessor 编译器选项时,定义为 0。 默认情况下,或者当设置了 /Zc:preprocessor- 编译器选项时,定义为 1,指示正在使用传统预处理器(实质上,即 /Zc:preprocessor 取代了已弃用的 /experimental:preprocessor)。
    #if !defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL
    // Logic using the traditional preprocessor
    #else
    // Logic using cross-platform compatible preprocessor
    #endif
    
  • _MT:当指定了 /MD/MDd(多线程 DLL),或者指定了 /MT/MTd(多线程)时,定义为 1。 其他情况下则不定义。

  • _NATIVE_WCHAR_T_DEFINED:当设置了 /Zc:wchar_t 编译器选项时,定义为 1。 其他情况下则不定义。

  • _OPENMP:如果设置了 (启用 OpenMP 2.0 支持)编译器选项,则定义为整数文本 200203/openmp。 此值表示 MSVC 实现 OpenMP 规范的日期。 其他情况下则不定义。

    // _OPENMP_dir.cpp
    // compile with: /openmp
    #include <stdio.h>
    int main() {
        printf("%d\n", _OPENMP);
    }
    
  • _PREFAST_:当设置了 /analyze 编译器选项时,定义为 1。 其他情况下则不定义。

  • __SANITIZE_ADDRESS__ 从 Visual Studio 2019 版本 16.9 开始提供。 当设置了 /fsanitize=address 编译器选项时,定义为 1。 其他情况下则不定义。

  • __TIMESTAMP__:定义为包含当前源文件上次修改日期和时间的字符串文本,并采用 CRT asctime 函数返回的恒定长度缩写格式,例如 Fri 19 Aug 13:32:58 2016。 任何情况下都会定义此宏。

  • _VC_NODEFAULTLIB:当设置了 (省略默认库名称)编译器选项,定义为 1/Zl。 其他情况下则不定义。

  • _WCHAR_T_DEFINED:当设置了默认 /Zc:wchar_t 编译器选项时,定义为 1。 但如果设置了 /Zc:wchar_t- 编译器选项并且在项目中包含的系统头文件中定义了 wchar_t,则会定义 _WCHAR_T_DEFINED 宏,但不会定义其值。 其他情况下则不定义。

  • _WIN32:当编译目标为 32 位 ARM、64 位 ARM、x86 或 x64 时,定义为 1。 其他情况下则不定义。

  • _WIN64:当编译目标为 64 位 ARM 或 x64 时,定义为 1。 其他情况下则不定义。

  • _WINRT_DLL:当编译为 C++,并且同时设置了 /ZW(Windows 运行时编译)/LD/LDd 编译器选项时,定义为 1。 其他情况下则不定义。

编译器未预定义用于识别 ATL 或 MFC 库版本的预处理器宏。 ATL 和 MFC 库头在内部定义这些版本宏。 在包含必需头之前实现的预处理器指令中,它们未定义。

  • _ATL_VER:在 <atldef.h> 中定义为编码 ATL 版本号的整数文本。

  • _MFC_VER:在 <afxver_.h> 中定义为编码 MFC 版本号的整数文本。

另请参阅

宏 (C/C++)
预处理器运算符
预处理器指令