MSVC (компилятор Microsoft C/C++) предоставляет предопределенные макросы препроцессора (predefined preprocessor macros), зависящие от используемого языка (C или C++), целевой платформы компиляции (compilation target) и выбранных опций компилятора.
MSVC поддерживает predefined preprocessor macros, требуемые стандартом ANSI/ISO C99 и стандартами ISO C++14 и C++17. Реализация компилятора также поддерживает некоторые макросы, больше специфичные именно для Microsoft. Некоторые макросы определены только для специфической платформы сборки или опций компилятора. Кроме случаев, где это отмечено, эти макросы определены в любом месте единицы трансляции, как если бы они были бы указаны с помощью аргументов опции /D компилятора. Будучи определенными, эти макросы разворачиваются препроцессором перед компиляцией в определенные значения. У predefined-макросов нет аргументов, и они не могут быть переопределены.
[__func__ - стандартный предопределенный идентификатор]
Компилятор поддерживает предопределенный идентификатор, предусмотренный стандартами ISO C99 и ISO C++11. Ключевое слово / макрос __func__ представляет неполное и "не украшенное" (т. е. без префиксов подчеркивания) имя окружающей функции (т. е. функции, где используется __func__) как статический массив символов (static const *char), в котором содержится имя функции.
Пример на C++, который напечатает имя функции "example":
void example()
{
// Выведется "example":
printf("%s\n", __func__);
}
[Стандартные предопределенные макросы]
Компилятор поддерживает следующие предопределенные макросы, описанные стандартами ISO C99 и ISO C++17.
__cplusplus Определен как целочисленный литерал, когда единица трансляции компилируется как код C++. Если это не так (например, идет компиляция кода как языка C), то __cplusplus не определен.
__DATE__ Дата компиляции текущего исходного файла. Дата это строковая константа постоянной длины в форме Mmm dd yyyy. Имя месяца Mmm такое же, как аббревиатурное имя месяца, генерируемое функцией asctime библиотеки C Runtime (CRT). Первый символ даты dd будет пробелом, если значение даты меньше 10. Этот макрос определен всегда.
__FILE__ Имя текущего исходного файла. Макрос __FILE__ разворачивается в символьный строковый литерал. Чтобы обеспечит полное имя файла в в этом литерале, используйте опцию /FC компилятора [2]. Этот макрос определен всегда.
__LINE__ Определен как целочисленный номер строки в текущем файле исходного кода. Значение макроса __LINE__ может быть изменено директивой #line. Этот макрос определен всегда.
__STDC__ Определен как 1 только когда модуль компилируется как код языка C, и если указана опция компилятора /Za [3]. Иначе макрос __STDC__ не определен.
__STDC_HOSTED__ Определен как 1, если это так называемая размещенная реализация (hosted implementation), поддерживающая всю необходимую стандартную библиотеку. Иначе __STDC_HOSTED__ определен как 0.
__STDCPP_THREADS__ Определен как 1, если и только если программа может иметь больше одного потока выполнения, и скомпилирована как код C++. Иначе макрос __STDCPP_THREADS__ не определен.
__TIME__ Представление времени обрабатываемого элемента трансляции. Время представлено литеральной строкой символов в форме hh:mm:ss, в таком же виде как время, возвращенная функцией asctime библиотеки CRT. Этот макрос определен всегда.
[Предопределенные макросы, специфические для Microsoft]
MSVC поддерживает следующие дополнительные predefined-макросы.
__ATOM__ Определен как 1, когда установлена опция компилятора /favor:ATOM, и цель компиляции x86 или x64. Иначе макрос __ATOM__ не определен.
__AVX__ Определен как 1, когда установлена опция компилятора /arch:AVX или /arch:AVX2, и цель компиляции x86 или x64. Иначе макрос __AVX__ не определен.
__AVX2__ Определен как 1, когда установлена опция компилятора /arch:AVX2, и цель компиляции x86 или x64. Иначе макрос __AVX2__ не определен.
_CHAR_UNSIGNED Определен как 1, когда тип по умолчанию для char без знака (unsigned). Это значение определено, когда установлена опция компилятора /J [4]. Иначе макрос _CHAR_UNSIGNED не определен.
__CLR_VER Определен как целочисленный литерал, представляющий версию общей языковой среды выполнения (Common Language Runtime, CLR), используемой для компиляции приложения. Это значение кодируется в виде Mmmbbbbb, где M это основная (major) версия исполняемого (runtime) кода, mm дополнительная (minor) версия runtime-кода, и bbbbb это номер сборки. Макрос __CLR_VER определен, если установлена опция компилятора /clr, иначе не определен.
Пример:
// clr_ver.cpp
// Скомпилировано с опцией /clr
using namespace System;
int main()
{
Console::WriteLine(__CLR_VER);
}
_CONTROL_FLOW_GUARD Определен как 1, когда установлена опция компилятора /guard:cf [5]. Иначе макрос _CONTROL_FLOW_GUARD не определен.
__COUNTER__ Раскрывается как целочисленный литерал, начинающийся с 0. Это значение инкрементируется на 1 каждый раз, когда макрос __COUNTER__ используется в исходном файле или заголовочном файле, подключенном в исходном файле. __COUNTER__ запоминает свое состояние, когда используются precompiled headers [26]. Этот макрос определен всегда.
Ниже показан пример, где __COUNTER__ используется для назначения уникальных идентификаторов трем разным объектам одинакового типа. Конструктор exampleClass принимает целое число в качестве параметра. В теле функции main приложение декларирует три объекта типа exampleClass, используя __COUNTER__ в качестве уникального идентификатора для параметра:
// macro__COUNTER__.cpp
// Демонстрация действия макроса __COUNTER__, назначающего уникальные
// идентификаторы разным объектам одного и того же типа.
// Компилируется командной строкой: cl /EHsc /W4 macro__COUNTER__.cpp
#include < stdio.h>
class exampleClass
{
int m_nID;
public:
// Инициализация объекта уникальным read-only ID:
exampleClass(int nID) : m_nID(nID) {}
int GetID(void) { return m_nID; }
};
int main()
{
// __COUNTER__ изначально определен как 0:
exampleClass e1(__COUNTER__);
// При следующем обращении __COUNTER__ будет теперь определен как 1:
exampleClass e2(__COUNTER__);
// __COUNTER__ теперь определен как 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());
// Вывод:
// ------------------------------
// e1 ID: 0
// e2 ID: 1
// e3 ID: 2
return 0;
}
__cplusplus_cli Определен как целое литеральное значение 200406, когда код компилируется как C++, и установлена опция компилятора /clr. Иначе __cplusplus_cli не определен. Будучи определенным, __cplusplus_cli действует на протяжении всей единицы трансляции.
Пример:
// cplusplus_cli.cpp
// Компилируется с опцией /clr
#include "stdio.h"
int main()
{
#ifdef __cplusplus_cli
printf("%d\n", __cplusplus_cli);
#else
printf("not defined\n");
#endif
}
__cplusplus_winrt Определен как целочисленный литерал со значением 201009, когда код компилируется как C++ и установлена опция компилятора /ZW [6]. Иначе __cplusplus_winrt не определен.
_CPPRTTI Определен как 1, если установлена опция компилятора /GR [7]. Иначе _CPPRTTI не определен.
_CPPUNWIND Определен как 1, если определена одна из опций (или большее их количество) /GX [8], /clr [9] или /EH [10]. Иначе _CPPUNWIND.
_DEBUG Определен как 1, когда установлена опция компилятора /LDd, /MDd или /MTd [11]. Иначе _DEBUG не определен.
_DLL Определен как 1, когда установлена опция компилятора /MD или /MDd (Multithreaded DLL) [11]. Иначе _DLL не определен.
__FUNCDNAME__ Определен как строковый литерал, содержащий декорированное имя функции, которая содержит в себе макрос __FUNCDNAME__. Этот макрос определен только внутри использующей его функции. Макрос __FUNCDNAME__ не раскрывается, если используются опции компилятора /EP [12] или /P [13].
Пример ниже использует макросы __FUNCDNAME__, __FUNCSIG__ и __FUNCTION__, чтобы показать информацию о функции.
// Демонстрация функционала макросов __FUNCTION__, __FUNCDNAME__ и __FUNCSIG__:
void exampleFunction()
{
printf("Function name: %s\n", __FUNCTION__);
printf("Decorated function name: %s\n", __FUNCDNAME__);
printf("Function signature: %s\n", __FUNCSIG__);
// Вывод этого примера:
// -------------------------------------------------
// Function name: exampleFunction
// Decorated function name: ?exampleFunction@@YAXXZ
// Function signature: void __cdecl exampleFunction(void)
}
__FUNCSIG__ Определен как строковый литерал, содержащий сигнатуру окружающей макрос функции. Этот макрос определен только в пределах использующей его функции. Макрос __FUNCSIG__ не разворачивается, если используются опции компиляции /EP или /P [12, 13]. Когда компиляция происходит для 64-битной цели, то умолчанию используется соглашение о вызовах (calling convention) __cdecl. Пример использования см. в описании макроса __FUNCDNAME__.
__FUNCTION__ Определен как строковый литерал, содержащий не декорированное имя окружающей макрос функции. Этот макрос определен только в пределах использующей его функции. Макрос __FUNCSIG__ не разворачивается, если используются опции компиляции /EP или /P [12, 13]. Пример использования см. в описании макроса __FUNCDNAME__.
_INTEGRAL_MAX_BITS Определен как целочисленный литерал со значением 64, показывающий максимальный размер (в битах) для не векторного целого типа. Этот макрос определен всегда.
// integral_max_bits.cpp
#include < stdio.h>
int main()
{
printf("%d\n", _INTEGRAL_MAX_BITS);
}
__INTELLISENSE__ Определен как 1 во время IntelliSense прохода компилятора в среде Visual Studio IDE. Иначе макрос __INTELLISENSE__ не определен. Вы можете использовать этот макрос для защиты кода, который не понимает IntelliSense-компилятор, или для переключения между сборкой и компилятором IntelliSense. Для дополнительной информации см. статью с описанием решения проблем с производительностью IntelliSense [14].
_ISO_VOLATILE Определен как 1, если установлена опция компилятора /volatile:iso [15], иначе не определен.
_KERNEL_MODE Определен как 1, если установлена опция компилятора /kernel [16], иначе не определен.
_M_AMD64 Определен как целочисленный литерал со значением 100 для компиляций, нацеленных на процессор x64, иначе не определен.
_M_ARM Определен как целочисленный литерал со значением 7 для компиляций, нацеленных на процессоры ARM, иначе не определен.
_M_ARM_ARMV7VE Определен как 1, когда установлена опция /arch:ARMv7VE [17] для компиляций, нацеленных на процессоры ARM, иначе не определен.
_M_ARM_FP Определен как целочисленное литеральное значение, которое показывает, какая была установлена опция /arch [17] для целевых процессоров ARM. Иначе макрос _M_ARM_FP не определен.
Значение макроса будет в диапазоне 30-39, если не была указана опция /arch ARM. Это показывает, что была установлена архитектура ARM по умолчанию (VFPv3). Значение в диапазоне 40-49, если была установлена опция /arch:VFPv4. Дополнительную информацию см. в [17].
_M_ARM64 Определен как 1 для компиляций, нацеленных на 64-битные процессоры ARM, иначе не определен.
_M_CEE Определен как 001, если установлена любая из опций компилятора /clr [9], иначе не определен.
_M_CEE_PURE Этот макрос устарел начиная с Visual Studio 2015. Определен как 001, если установлена опция компилятора /clr:pure [9], иначе не определен.
_M_CEE_SAFE Этот макрос устарел начиная с Visual Studio 2015. Определен как 001, если установлена опция компилятора /clr:safe [9], иначе не определен.
_M_FP_EXCEPT Определен как 1, если установлена опция компилятора /fp:except или /fp:strict [18], иначе не определен.
_M_FP_FAST Определен как 1, если установлена опция компилятора /fp:fast [18], иначе не определен.
_M_FP_PRECISE Определен как 1, если установлена опция компилятора /fp:precise [18], иначе не определен.
_M_FP_STRICT Определен как 1, если установлена опция компилятора /fp:strict [18], иначе не определен.
_M_IX86 Определен как целочисленный литерал 600 для компиляций, нацеленных на процессоры x86. Этот макрос не определен для целей компиляции x64 или ARM.
_M_IX86_FP Определен как целочисленный литерал, который показывает какая опция /arch [17] компилятора была установлена, или установку по умолчанию. Макрос _M_IX86_FP всегда определен, когда цель компиляции процессор x86, иначе макрос не определен. Когда макрос _M_IX86_FP определен, его значение следующее:
0 если была установлена опция компилятора /arch:IA32. 1 если была установлена опция компилятора /arch:SSE. 2 если была установлена опция компилятора /arch:SSE2, /arch:AVX или /arch:AVX2. Это значение по умолчанию, если не была указана опция компилятора /arch. Когда указана опция /arch:AVX, также будет определен макрос __AVX__. Когда указана опция /arch:AVX2, также будут определены оба макроса __AVX__ и __AVX2__.
Для дополнительной информации см. /arch (x86) [17].
_M_X64 Определен как целочисленный литерал со значением 100 для компиляций, нацеленных на процессоры x64, иначе не определен.
_MANAGED Определен как 1, когда установлена опция компилятора /clr [9], иначе не определен.
_MSC_BUILD Определен как целочисленный литерал, который содержит элемент номера ревизии от номера версии компилятора. Номер ревизии это четвертый элемент из номера версии, где отдельные элементы отделены друг от друга точками. Например, если номер версии компилятора Microsoft C/C++ 15.00.20706.01, то макрос _MSC_BUILD будет вычислен как 1. Этот макрос определен всегда.
_MSC_EXTENSIONS Определен как 1, если установлена опция компилятора /Ze [3], иначе не определен.
_MSC_FULL_VER Определен как целочисленный литерал, кодирующий элементы major, minor и build номера версии компилятора. Номер major это первый элемент версии компилятора, minor второй элемент, и build третий элемент. Например, если номер версии компилятора Microsoft C/C++ 15.00.20706.01, то макрос _MSC_FULL_VER вычисляется как 150020706. Чтобы узнать номер версии компилятора, выполните команду cl /?. Этот макрос определен всегда.
_MSC_VER Определен как целочисленный литерал, кодирующий элементы major и minor номера версии компилятора. Номер major это первый элемент версии компилятора, minor второй элемент. Например, если номер версии компилятора Microsoft C/C++ 17.00.51106.1, то макрос _MSC_VER будет вычислен как 1700. Чтобы узнать номер версии компилятора, выполните команду cl /?. Этот макрос определен всегда.
Версия Visual Studio |
_MSC_VER |
Visual Studio 6.0 |
1200 |
Visual Studio .NET 2002 (7.0) |
1300 |
Visual Studio .NET 2003 (7.1) |
1310 |
Visual Studio 2005 (8.0) |
1400 |
Visual Studio 2008 (9.0) |
1500 |
Visual Studio 2010 (10.0) |
1600 |
Visual Studio 2012 (11.0) |
1700 |
Visual Studio 2013 (12.0) |
1800 |
Visual Studio 2015 (14.0) |
1900 |
Visual Studio 2017 RTW (15.0) |
1910 |
Visual Studio 2017 version 15.3 |
1911 |
Visual Studio 2017 version 15.5 |
1912 |
Visual Studio 2017 version 15.6 |
1913 |
Visual Studio 2017 version 15.7 |
1914 |
Visual Studio 2017 version 15.8 |
1915 |
Visual Studio 2017 version 15.9 |
1916 |
Visual Studio 2019 RTW (16.0) |
1920 |
Чтобы проверить релизы компилятора или обновления для имеющейся версии Visual Studio или более свежих версий, используйте оператор >=. Вы можете использовать директиву условной компиляции препроцессора #if, чтобы сравнить _MSC_VER и известными значениями версий компилятора. Если у Вас имеется несколько взаимоисключающий версий компилятора для сравнения, то постройте список сравнения в порядке убывания номера версии. Ниже для примера показан код, проверяющий версии компилятора, находящиеся в Visual Studio 2017 и более свежих версиях этой IDE. Вторая проверка - релизы компиляторов Visual Studio 2015 и более свежие, но не свежее Visual Studio 2017. Завершающая ветка #else отфильтровывает все версии компиляторов, которые старее Visual Studio 2015:
#if _MSC_VER >= 1910
// ...
#elif _MSC_VER >= 1900
// ...
#else
// ...
#endif
Также см. статью о версиях компиляторов MSVC [19].
_MSVC_LANG Определен как целочисленный литерал, показывающий стандарт языка C++, на который нацелен компилятор. Этот макрос устанавливается только в коде, скомпилированном как C++. По умолчанию, или когда указана опция компилятора /std:c++14, значение макроса _MSVC_LANG будет 201402L. Макрос установится в значение 201703L, если была указана опция /std:c++17 компилятора. Макрос получит большее, не указанное значение, когда указана опция /std:c++latest. Иначе макрос _MSVC_LANG не определен. Макрос _MSVC_LANG и опция компилятора /std [20] впервые появилась в релизе Visual Studio 2015 Update 3.
__MSVC_RUNTIME_CHECKS Определен как 1, когда установлена одна из опций компилятора /RTC, иначе не определен.
_MT Определен как 1, когда указана опция компилятора /MD, или /MDd, или /MT, или /MTd [11], иначе не определен.
_NATIVE_WCHAR_T_DEFINED Определен как 1, когда установлена опция компилятора /Zc:wchar_t [22], иначе не определен.
_OPENMP Определен как целочисленный литерал 200203, если установлена опция компилятора /openmp [23]. Это значение представляет дату спецификации OpenMP, реализованной MSVC. Иначе макрос _OPENMP не определен.
// _OPENMP_dir.cpp
// Компилировалось с опцией /openmp
#include < stdio.h>
int main()
{
printf("%d\n", _OPENMP);
}
_PREFAST_ Определен как 1, когда установлена опция компилятора /analyze [24], иначе не определен.
__TIMESTAMP__ Определен как как литеральная строка символов, содержащая дату и время последней модификации исходного файла. Строка имеет постоянную длину и сформирована в аббревиатурной форме, где содержится время и дата, как они выводятся функцией asctime библиотеки CRT. Например, Fri 19 Aug 13:32:58 2016. Этот макрос определен всегда.
_VC_NODEFAULTLIB Определен как 1, когда установлена опция компилятора /Zl [25], иначе не определен.
_WCHAR_T_DEFINED Определен как 1, когда установлена по умолчанию опция компилятора /Zc:wchar_t [22]. Макрос _WCHAR_T_DEFINED определен, но у него нет значения, если была установлена опция компилятора /Zc:wchar_t-, и wchar_t определен системным заголовочным файлом, подключенным к проекту. Иначе макрос _WCHAR_T_DEFINED не определен.
_WIN32 Определен как 1, когда цель компиляции 32-bit ARM, 64-bit ARM, x86 или x64. Иначе макрос _WIN32 не определен.
_WIN64 Определен как 1, когда цель компиляции 64-bit ARM или x64, иначе не определен.
_WINRT_DLL Определен как 1, когда код компилируется как C++, и установлены обе опции компилятора /ZW [6] и /LD или /LDd [11]. Иначе макрос _WINRT_DLL не определен.
Не существует макросов препроцессора компилятора, которые идентифицировали бы версию библиотеки ATL или MFC. Заголовочные файлы библиотек ATL и MFC внутри себя определяют эти макросы версий. Их определение отменяется директивами препроцессора перед тем, как подключается требуемый заголовочный файл.
_ATL_VER Определен в заголовке < atldef.h> как целочисленный литерал, кодирующий номер версии ATL.
_MFC_VER Определен в заголовке < afxver_.h> как целочисленный литерал, кодирующий номер версии MFC.
[Ссылки]
1. Predefined Macros site:docs.microsoft.com. 2. /FC (Full Path of Source Code File in Diagnostics) site:docs.microsoft.com. 3. /Za, /Ze (Disable Language Extensions) site:docs.microsoft.com. 4. /J (Default char Type Is unsigned) site:docs.microsoft.com. 5. /guard (Enable Control Flow Guard) site:docs.microsoft.com. 6. /ZW (Windows Runtime Compilation) site:docs.microsoft.com. 7. /GR (Enable Run-Time Type Information) site:docs.microsoft.com. 8. /GX (Enable Exception Handling) site:docs.microsoft.com. 9. /clr (Common Language Runtime Compilation) site:docs.microsoft.com. 10. /EH (Exception Handling Model) site:docs.microsoft.com. 11. /MD, /MT, /LD (Use Run-Time Library) site:docs.microsoft.com. 12. /EP (Preprocess to stdout Without #line Directives) site:docs.microsoft.com. 13. /P (Preprocess to a File) site:docs.microsoft.com. 14. Troubleshooting Tips for IntelliSense Slowness site:devblogs.microsoft.com. 15. /volatile (volatile Keyword Interpretation) site:docs.microsoft.com. 16. /kernel (Create Kernel Mode Binary) site:docs.microsoft.com. 17. /arch (ARM) site:docs.microsoft.com. 18. /fp (Specify floating-point behavior) site:docs.microsoft.com. 19. Visual C++ Compiler Version site:devblogs.microsoft.com. 20. /std (Specify Language Standard Version) site:devblogs.microsoft.com. 21. /RTC (Run-Time Error Checks) site:devblogs.microsoft.com. 22. /Zc:wchar_t (wchar_t Is Native Type) site:devblogs.microsoft.com. 23. /openmp (Enable OpenMP 2.0 Support) site:devblogs.microsoft.com. 24. /analyze (Code Analysis) site:devblogs.microsoft.com. 25. /Zl (Omit Default Library Name) site:devblogs.microsoft.com. 26. Visual Studio: /Yc, /Yu, #pragma hdrstop, stdafx.h. |