预定义宏
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 支持其他预定义宏:
__ARM_ARCH
定义为表示 ARM 体系结构版本的整数文本。 该值定义为 Armv8-A 体系结构的 8。 对于 8.1 及更高版本,使用 ARM C 语言扩展定义的公式 X * 100 + Y 来缩放次要版本(如 X.Y)的值。 例如,对于 Armv8.1,__ARM_ARCH
为 8 * 100 + 1 或 801。 若要设置 ARM 体系结构版本,请参阅/arch (ARM64)
。 此宏是在 Visual Studio 2022 版本 17.10 中引入的。__ATOM__
当设置了 编译器选项,并且编译器目标为 x86 或 x64 时,定义为 1/favor:ATOM
。 其他情况下则不定义。__AVX__
当设置或/arch:AVX512
/arch:AVX10.1
编译器选项且编译器目标为 x86 或 x64 时/arch:AVX
/arch:AVX2
定义为 1。 其他情况下则不定义。__AVX2__
在设置或/arch:AVX10.1
编译器选项且编译器目标为 x86 或 x64 时/arch:AVX2
/arch:AVX512
定义为 1。 其他情况下则不定义。__AVX512BW__
:当设置了/arch:AVX512
或/arch:AVX10.1
编译器选项,并且编译器目标为 x86 或 x64 时,定义为 1。 其他情况下则不定义。__AVX512CD__
:当设置了/arch:AVX512
或/arch:AVX10.1
编译器选项,并且编译器目标为 x86 或 x64 时,定义为 1。 其他情况下则不定义。__AVX512DQ__
:当设置了/arch:AVX512
或/arch:AVX10.1
编译器选项,并且编译器目标为 x86 或 x64 时,定义为 1。 其他情况下则不定义。__AVX512F__
:当设置了/arch:AVX512
或/arch:AVX10.1
编译器选项,并且编译器目标为 x86 或 x64 时,定义为 1。 其他情况下则不定义。__AVX512VL__
:当设置了/arch:AVX512
或/arch:AVX10.1
编译器选项,并且编译器目标为 x86 或 x64 时,定义为 1。 其他情况下则不定义。__AVX10_VER__
定义为一个整数,表示当设置编译器选项且编译器目标为 x86 或 x64 时/arch:AVX10.1
AVX10 的版本。 其他情况下则不定义。_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 开始的整数文本。 该值每次在源文件中使用或包含在源文件的标头中时递增 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。 其他情况下则不定义。__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:AVX
、/arch:AVX2
或/arch:AVX10.1
编译器选项,/arch:AVX512
则/arch:SSE2
为 2。 如果未指定/arch
编译器选项,则为默认值。 当指定了/arch:AVX
时,还会定义宏__AVX__
。 当指定了/arch:AVX2
时,还会定义__AVX__
和__AVX2__
。 当指定了/arch:AVX512
时,还会定义__AVX__
、__AVX2__
、__AVX512BW__
、__AVX512CD__
、__AVX512DQ__
、__AVX512F__
和__AVX512VL__
。 指定时/arch:AVX10.1
、__AVX__
、、__AVX2__
__AVX512BW__
、__AVX512CD__
、__AVX512DQ__
、__AVX512F__
__AVX512VL__
和__AVX10_VER__
也定义。有关详细信息,请参阅 (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
- 从 Visual Studio 2017 版本 15.8 开始可用:在设置预处理器一致性模式
_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__
:定义为包含当前源文件上次修改日期和时间的字符串文本,并采用 CRTasctime
函数返回的恒定长度缩写格式,例如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 版本号的整数文本。