Предопределённые макросы
========================

.. contents::
   :local:

.. toctree::
   :hidden:

Что такое предопределённые макросы и как их посмотреть
------------------------------------------------------

Любая программа работает в некотором системном окружении. Общепринято,
что информация о системном окружении и режимах трансляции передается
от компилятора программе через предустановленные макроопределения.
Ниже приведены имена и значения основных предопределенных макроопределений
компилятора и описаны случаи, при которых они выставляются

Предопределённые макросы можно посмотреть следующим образом:

.. code-block:: bash

  $ lcc -dM -E -xc /dev/null

Данный запуск покажет все установленные на конец препроцессирования макросы.
Поскольку мы подаём пустой файл в режиме Си, то это означает, что мы увидим все
предустановленные макросы в режиме Си. Если нужен режим Си++, то вместо опции
``-xc`` нужно подать опцию ``-xc++``. Если подать опцию ``-mptr128``,
то в печати дополнительно появятся макросы, которые включается в защищённом режиме,
если подать опцию ``-O2``, то в печати дополнительно появятся макросы, которые
включаются в режиме с оптимизациями и т.п.

Предопределённый макрос эквивалентен тому, что в в самом начале каждого
компилируемого файла из командной строки появляется соответствующая директива
``#define``. Или, что тоже самое, в компиляцию подаются соответствующие опции
``-D``. По правилам языков Си/Си++ при наличии конструкции типа ``#define XXX``
(т.е. задаётся имя макроса, но не задаётся его значение) макрос устанавливается
в значение ``1``. То же самое касается и предопределённых макросов. Т.е. если
в описании просто задано имя макроса, то в соотвествии с правилами значение
макроса будет выставлено в ``1``. За исключением случаев, когда это явным образом оговорено

Макросы, помеченные как "DEPRECATED", возможно, в будущем будут удалены,
а потому их НЕ рекомендуется использовать

Макросы, определяющие целевую архитектуру
-----------------------------------------

Макросы архитектуры семейства E2K:

* **__e2k__**
* **__iset__=2** взводится в режимах ``-march=elbrus-v2``, ``-mtune=elbrus-2c+``
* **__iset__=3** взводится в режимах ``-march=elbrus-v3``, ``-mtune=elbrus-4c``
* **__iset__=4** взводится в режимах ``-march=elbrus-v4``, ``-mtune=elbrus-8c``, ``-mtune=elbrus-1c+``
* **__iset__=5** взводится в режимах ``-march=elbrus-v5``, ``-mtune=elbrus-8c2``
* **__iset__=6** взводится в режимах ``-march=elbrus-v6``, ``-mtune=elbrus-12c``, ``-mtune=elbrus-16c``, ``-mtune=elbrus-2c3``
* **__elbrus_2cplus__** взводится в режиме ``-mtune=elbrus-2c+``
* **__elbrus_4c__** взводится в режиме ``-mtune=elbrus-4c``
* **__elbrus_8c__** взводится в режиме ``-mtune=elbrus-8c``
* **__elbrus_1cplus__** взводится в режиме ``-mtune=elbrus-1c+``
* **__elbrus_8c2__** взводится в режиме ``-mtune=elbrus-8c2``
* **__elbrus_12c__** взводится в режиме ``-mtune=elbrus-12c````
* **__elbrus_16c__** взводится в режиме ``-mtune=elbrus-16c``
* **__elbrus_2c3__** взводится в режиме ``-mtune=elbrus-2c3``

Макросы архитектуры семейства E90:

* **__sparc**, **__sparc__**, **sparc** последний взводится только при отсутствии режима ``-ansi``
* **__sparcv9** взводится в режиме -m64 (DEPRECATED)
* **__sparc_v8__** взводится в режиме ``-mcpu=v8``
* **__sparc_v9__** взводится в режимах ``-mcpu=v9``, ``-mcpu=ultrasparc``, ``-mcpu=ultrasparc3``, ``-mcpu=r1000``, ``-mcpu=r2000``, ``-mcpu=r2000+``
* **__r1000__** взводится в режиме ``-mcpu=r1000``
* **__r2000__** взводится в режиме ``-mcpu=r2000``
* **__r2000plus__** взводится в режиме ``-mcpu=r2000+``
* **__arch64__** взводится в режиме ``-m64``

Макросы, определяющие режимы адресации:

* **__ptr32__** для E2K в режиме ``-mptr32``, для E90 в режиме ``-m32``
* **__ptr64__** для E2K в режиме ``-mptr64``, для E90 в режиме ``-m64``
* **__ptr128__** для E2K в режиме ``-mptr128``
* **__PROTECTED__** эквивалентен **__ptr128__** (DEPRECATED)
* **__64__** для E2K в единственно возможном режиме ``-mptr64`` на операционной системе qnx (КПДА)
* **_LP64**, **__LP64__** для E2K в режиме ``-mptr64``, для E90 в режиме ``-m64``

Макросы, определяющие целевую операционную систему
--------------------------------------------------

* **__gnu_linux__**, **__linux**, **__linux__**, **linux** взводится для компиляторов под linux. Последний взводится только при отсутствии режима ``-ansi``
* **__QNXNTO__**, **__QNX__** взводится для компиляторов под qnx (КПДА)

Макросы, определяющие характеристики базовых и стандартных типов
----------------------------------------------------------------

Данные макросы введены для совместимости с компилятором gcc и используются
в том числе и в стандартных заголовочных файлах limits.h и float.h

Макросы, задающие байтовые размеры типов:

* **__CHAR_BIT__=8**
* **__SIZEOF_SHORT__=2**
* **__SIZEOF_INT__=4**
* **__SIZEOF_LONG__=<val>** для E2K в режиме ``-mptr32``, E90 в режиме ``-m32`` **<val>** равно **4**, в остальных случаях - **8**
* **__SIZEOF_LONG_LONG__=8**
* **__SIZEOF_INT128__=16** кроме E90 режима ``-m32``
* **__SIZEOF_FLOAT__=4**
* **__SIZEOF_DOUBLE__=8**
* **__SIZEOF_LONG_DOUBLE__=16**
* **__SIZEOF_FLOAT128__=16**
* **__SIZEOF_POINTER__=<val>** для E2K в режиме ``-mptr128`` **<val>** равно **16**, для E2K в режиме ``-mptr32``, E90 в режиме ``-m32`` **<val>** равно **4**, в остальных случаях - **8**
* **__SIZEOF_SIZE_T__=<val>** для E2K в режиме ``-mptr32``, E90 в режиме ``-m32`` **<val>** равно **4**, в остальных случаях - **8**
* **__SIZEOF_PTRDIFF_T__=<val>** для E2K в режиме ``-mptr32``, E90 в режиме ``-m32`` **<val>** равно **4**, в остальных случаях - **8**
* **__SIZEOF_WCHAR_T__=4**
* **__SIZEOF_WINT_T__=4**

Макросы, задающие битовые размеры типов:

* **__SCHAR_WIDTH__** - битовый размер типа ``char``
* **__SHRT_WIDTH__** - битовый размер типа ``short``
* **__INT_WIDTH__** - битовый размер типа ``int``
* **__LONG_WIDTH__** - битовый размер типа ``long``
* **__LONG_LONG_WIDTH__** - битовый размер типа ``long long``
* **__PTRDIFF_WIDTH__** - битовый размер типа ``ptrdiff_t``
* **__SIG_ATOMIC_WIDTH__** - битовый размер типа ``sig_atomic_t``
* **__SIZE_WIDTH__** - битовый размер типа ``size_t``
* **__WCHAR_WIDTH__** - битовый размер типа ``wchar_t``
* **__WINT_WIDTH__** - битовый размер типа ``wint_t``
* **__INT_LEAST8_WIDTH__** - битовый размер типа ``int_least8_t``
* **__INT_LEAST16_WIDTH__** - битовый размер типа ``int_least16_t``
* **__INT_LEAST32_WIDTH__** - битовый размер типа ``int_least32_t``
* **__INT_LEAST64_WIDTH__** - битовый размер типа ``int_least64_t``
* **__INT_FAST8_WIDTH__** - битовый размер типа ``int_fast8_t``
* **__INT_FAST16_WIDTH__** - битовый размер типа ``int_fast16_t``
* **__INT_FAST32_WIDTH__** - битовый размер типа ``int_fast32_t``
* **__INT_FAST64_WIDTH__** - битовый размер типа ``int_fast64_t``
* **__INTPTR_WIDTH__** - битовый размер типа ``intptr_t``
* **__INTMAX_WIDTH__** - битовый размер типа ``intmax_t``

Макросы, задающие максимальные величины целочисленных типов:

* **__SIGNED_CHARS__** - при отсутствии режима ``-funsigned-chars``
* **__SCHAR_MAX__=127**
* **__SHRT_MAX__=32767**
* **__INT_MAX__=2147483647**
* **__LONG_MAX__=<val>** для E2K в режиме ``-mptr32``, E90 в режиме ``-m32`` **<val>** равно **2147483647L**, в остальных случаях - **9223372036854775807L**
* **__LONG_LONG_MAX__=9223372036854775807LL**
* **__INTMAX_MAX__=9223372036854775807LL**
* **__WCHAR_MAX__=2147483647**
* **__WCHAR_MIN__=(-__WCHAR_MAX__ - 1)**
* **__WINT_MAX__=4294967295U**
* **__WINT_MIN__=0U**
* **__PTRDIFF_MAX__=<val>** для E2K в режимах ``-mptr64`` и ``-mptr128``, E90 в режиме ``-m64`` **<val>** равно **9223372036854775807L**, для E2K в режиме ``-mptr32`` **<val>** равно **2147483647L**, для E90 в режиме ``-m32`` **<val>** равно **2147483647**
* **__SIZE_MAX__=<val>** для E2K в режимах ``-mptr64`` и ``-mptr128``, E90 в режиме ``-m64`` **<val>** равно **18446744073709551615UL**, для E2K в режиме ``-mptr32`` **<val>** равно **4294967295UL**, для E90 в режиме ``-m32`` **<val>** равно **4294967295U**

Макросы, задающие стандартные типы из stddef.h:

* **__SIZE_TYPE__=<val>** описывает тип ``size_t``. Для E2K в режиме ``-mptr32``, E90 в режиме ``-m32`` **<val>** равно **unsigned int**, в остальных случаях - **unsigned long**
* **__PTRDIFF_TYPE__=<val>** описывает тип ``ptrdiff_t``. Для E2K в режиме ``-mptr32``, E90 в режиме ``-m32`` **<val>** равно **int**, в остальных случаях - **long**
* **__WCHAR_TYPE__=int** описывает тип ``wchar_t``

Макросы, задающие характеристики типа ``float``:

* **__FLT_RADIX__=2**
* **__FLT_EVAL_METHOD__=0**
* **__FLT_MANT_DIG__=24**
* **__FLT_DIG__=6**
* **__FLT_MIN_EXP__=(-125)**
* **__FLT_MIN_10_EXP__=(-37)**
* **__FLT_MAX_EXP__=128**
* **__FLT_MAX_10_EXP__=38**
* **__FLT_MIN__=1.175494351E-38F**
* **__FLT_MAX__=3.402823466E+38F**
* **__FLT_EPSILON__=1.192092896E-07F**
* **__FLT_DENORM_MIN__=1.40129846e-45F**
* **__FLT_HAS_INFINITY__=1**
* **__FLT_HAS_QUIET_NAN__=1**
* **__FLT_HAS_DENORM__=1**

Макросы, задающие характеристики типа ``double``:

* **__DBL_MANT_DIG__=53**
* **__DBL_DIG__=15**
* **__DBL_MIN_EXP__=(-1021)**
* **__DBL_MIN_10_EXP__=(-307)**
* **__DBL_MAX_EXP__=1024**
* **__DBL_MAX_10_EXP__=308**
* **__DBL_MIN__=2.2250738585072014E-308**
* **__DBL_MAX__=1.7976931348623157E+308**
* **__DBL_EPSILON__=2.2204460492503131E-16**
* **__DBL_DENORM_MIN__=4.9406564584124654e-324**
* **__DBL_HAS_INFINITY__=1**
* **__DBL_HAS_QUIET_NAN__=1**
* **__DBL_HAS_DENORM__=1**

Макросы, задающие характеристики типа ``long double`` на E2K (взводятся только на E2K):

* **__LDBL_MANT_DIG__=64**
* **__LDBL_DIG__=18**
* **__LDBL_DECIMAL_DIG__=21**
* **__LDBL_MIN_EXP__=(-16381)**
* **__LDBL_MIN_10_EXP__=(-4931)**
* **__LDBL_MAX_EXP__=16384**
* **__LDBL_MAX_10_EXP__=4932**
* **__LDBL_MIN__=3.3621031431120935062627E-4932L**
* **__LDBL_MAX__=1.1897314953572317650213E+4932L**
* **__LDBL_EPSILON__=1.0842021724855044340075E-19L**
* **__LDBL_DENORM_MIN__=3.64519953188247460253e-4951L**
* **__LDBL_HAS_INFINITY__=1**
* **__LDBL_HAS_QUIET_NAN__=1**
* **__LDBL_HAS_DENORM__=1**
* **__DECIMAL_DIG__=21**

Макросы, задающие характеристики типа ``long double`` на E90 (взводятся только на E90):

* **__LDBL_MANT_DIG__=113**
* **__LDBL_DIG__=33**
* **__LDBL_DECIMAL_DIG__=36**
* **__LDBL_MIN_EXP__=(-16381)**
* **__LDBL_MIN_10_EXP__=(-4931)**
* **__LDBL_MAX_EXP__=16384**
* **__LDBL_MAX_10_EXP__=4932**
* **__LDBL_MIN__=3.362103143112093506262677817321752603E-4932L**
* **__LDBL_MAX__=1.189731495357231765085759326628007016E+4932L**
* **__LDBL_EPSILON__=1.925929944387235853055977942584927319E-34L**
* **__LDBL_DENORM_MIN__=6.47517511943802511092443895822764655e-4966L**
* **__LDBL_HAS_INFINITY__=1**
* **__LDBL_HAS_QUIET_NAN__=1**
* **__LDBL_HAS_DENORM__=1**
* **__DECIMAL_DIG__=36**

Исторические рудименты:

* **__LONG_DOUBLE_128__** взводится для E90 в режиме ``-m32``

Макросы для имитации поведения gcc под x86
------------------------------------------

Данные макросы поддерживаются только на E2K

* **__MMX__** - в режиме ``-mmmx``
* **__SSE__** - в режиме ``-msse``
* **__SSE2__** - в режиме ``-msse2``
* **__SSSE3__** - в режиме ``-msse3``
* **__SSE4_1__** - в режиме ``-msse4.1``
* **__SSE4_2__** - в режиме ``-msse4.1``
* **__AVX__** - в режиме ``-mavx``
* **__3dNOW__** - в режиме ``-m3dnow``
* **__3dNOW_A__** - в режиме ``-m3dnowa``
* **__SSE4A__** - в режиме ``-msse4a``
* **__FMA4__** - в режиме ``-mfma4``
* **__XOP__** - в режиме ``-mxop``
* **__AES__** - в режиме ``-maes``
* **__PCLMUL__** - в режиме ``-mpclmul``
* **__RDRND__** - в режиме ``-mrdrnd``
* **__BMI__** - в режиме ``-mbmi``
* **__TBM__** - в режиме ``-mtbm``
* **__ABM__** - в режиме ``-mabm``
* **__F16C__** - в режиме ``-mf16c``
* **__POPCNT__** - в режиме ``-mpopcnt``
* **__RDSEED__** - в режиме ``-mrdseed``
* **__LZCNT__** - в режиме ``-mlzcnt``
* **__MWAITX__** - в режиме ``-mmwaitx``
* **__CLZERO__** - в режиме ``-mclzero``
* **__CLFLUSHOPT__** - в режиме ``-mclflushopt``
* **__CLWB__** - в режиме ``-mclwb``
* **__BMI2__** - в режиме ``-mbmi2``
* **__FMA__** - в режиме ``-mfma``
* **__AVX2__** - в режиме ``-mavx2``
* **__SHA__** - в режиме ``-msha``

Прочие макросы, которые взводятся всегда
----------------------------------------

Оговоримся, что подразумевается под "всегда". Есть макросы, которые взводятся
только для E2K, но не взводятся для E90. В этом смысле по отношению к E2K это
означает "всегда". Есть макросы, которые взводятся всегда, но в зависимости
от целевой архитектуры значение макроса может меняться. Но по отношению к тому,
что макрос присутствует или отсутсвует это так же означает "всегда"

* **__MCST__**
* **__LCC__=126** соответствует первым двум числам версии компилятора
* **__LCC_MINOR__=<val>** значение равно последнему числу в номере версии компилятора. Например, для версии компилятора 1.26.06, **<val>** равно **6**
* **__unix**, **__unix__**, **unix** последний взводится только при отсутствии режима ``-ansi``
* **__ELF__**
* **__LONG_DOUBLE__=<val>** для E2K **<val>** равно **80**, для E90 - **128**
* **_LITTLE_ENDIAN** взводится только для E2K (DEPRECATED)
* **__ORDER_LITTLE_ENDIAN__=1234**
* **__ORDER_BIG_ENDIAN__=4321**
* **__ORDER_PDP_ENDIAN__=3412**
* **__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__** взводится только для E2K
* **__FLOAT_WORD_ORDER__=__ORDER_LITTLE_ENDIAN__** взводится только для E2K
* **__BYTE_ORDER__=__ORDER_BIG_ENDIAN__** взводится только для E90
* **__FLOAT_WORD_ORDER__=__ORDER_BIG_ENDIAN__** взводится только для E90
* **__PRAGMA_REDEFINE_EXTNAME**
* **__STDC__**
* **__DATE__=<val>** выставляется в строковой литерал с датой компиляции, например **"Feb 13 2012"**
* **__TIME__=<val>** выставляется в строковой литерал с временем компиляции, например **"13:48:01"**
* **__FILE__=<val>** выставляется в строковой литерал с именем файла, соответствующего точке использования макроса, например **"t.c"**
* **__LINE__=<val>** выставляется в номер строки, соответствующего точке использования макроса, например **10**
* **__USER_LABEL_PREFIX__** значение макроса равно пустышке (а не **1**, как это бы следовало из общих правил)
* **__REGISTER_PREFIX__** значение макроса равно пустышке (а не **1**, как это бы следовало из общих правил)
* **__GFORTRAN__** взводится при запуске lfortran'а

Прочие макросы, которые взводятся в зависимости от поданных опций
-----------------------------------------------------------------

* **__STRICT_ANSI__** в режимах ``-ansi``, ``-std=c89``, ``-std=iso9899:1990``, ``-std=iso9899:199409``, ``-std=c99``, ``-std=c9x``, ``-std=iso9899:1999``, ``-std=c11``, ``-std=c1x``, ``-std=iso9899:2011``, ``-std=c17``, ``-std=c18``, ``-std=iso9899:2017``, ``-std=iso9899:2018``, ``-std=c++98``, ``-std=c++11``, ``-std=c++0x``, ``-std=c++14``, ``-std=c++1y``, ``-std=c++17``, ``-std=c++1z``, ``-std=c++2a``
* **__OPTIMIZE__** в режимах с оптимизациями
* **__FAST_MATH__** в режиме ``-ffast-math``
* **__EXCEPTIONS** в режиме ``-fexceptions``
* **_REENTRANT** в режиме ``-pthreads``
* **__VIS=<val>** только для E90 в режиме ``-mvis``: в режиме ``-mcpu=ultrasparc`` **<val>** равно **0x100**, в режиме ``-mcpu=ultrasparc3`` - **0x200**, в режимах ``-mcpu=r1000`` и ``-mcpu=r2000`` - **0x300**, в режиме ``-mcpu=r2000+`` - **0x400**
* **_OPENMP=201107** - в режиме ``-fopenmp``
* **__NO_INLINE__** в случае если НЕ используются оптимизации и НЕ используется профилирование
* **_GNU_SOURCE** в режиме C++
* **__GXX_WEAK__** в режиме C++
* **__DEPRECATED** в режиме C++ ``-Wdeprecated``
* **__STDC_VERSION__=<val>** в режиме языка C99 и выше. В режиме C99 **<val>** равно **199901L**, в режиме C11 **<val>** равно **201112L**, в режиме C18 **<val>** равно **201710L**
* **__STDC_HOSTED__** в режиме языка C99 и выше
* **__cplusplus=<val>** в режиме языка C++. В режиме C++98/C++03 **<val>** равно **199711L**, в режиме C++11 **<val>** равно **201103L**, в режиме C++14 **<val>** равно **201402L**, в режиме C++17 **<val>** равно **201703L**, в режиме C++20 **<val>** равно **202002L**
* **_WCHAR_T** в режиме языка C++. Макрос означает наличие поддержки ключевого слова ``wchar_t``
* **_BOOL** в режиме языка C++. Макрос означает наличие поддержки ключевого слова ``bool``
* **__ARRAY_OPERATORS** в режиме языка C++. Макрос означает наличие поддержки операторов ``new[]`` и ``delete[]``
* **__RTTI** в режиме языка C++ в режиме ``-frtti``. Макрос означает наличие поддержки RTTI (Run-Time Type Information)
* **__PLACEMENT_DELETE** в режиме языка C++. Макрос означает наличие поддержки оператора "placement delete"
* **__EDG_RUNTIME_USES_NAMESPACES** в режиме языка C++
* **__EDG_IA64_ABI** в режиме языка C++. Макрос означает использование IA64_ABI при работе с Си++
* **__EDG_IA64_ABI_USE_INT_STATIC_INIT_GUARD** в режиме языка C++
* **__EDG_TYPE_TRAITS_ENABLED** в режиме языка C++ в режиме ``-fno-gnu``
* **__GNUC__=<val>** в режиме ``-gcc-version 930`` (по умолчанию) **<val>** равно **9**, в режиме ``-gcc-version 730`` **<val>** равно **7**, в режиме ``-gcc-version 550`` **<val>** равно **5**, в режиме ``-gcc-version 480`` **<val>** равно **4**, в режиме ``-gcc-version 440`` **<val>** равно **4**
* **__GNUC_MINOR__=<val>** в режиме ``-gcc-version 930`` (по умолчанию) **<val>** равно **3**, в режиме ``-gcc-version 730`` **<val>** равно **3**, в режиме ``-gcc-version 550`` **<val>** равно **5**, в режиме ``-gcc-version 480`` **<val>** равно **8**, в режиме ``-gcc-version 440`` **<val>** равно **4**
* **__GNUC_PATCHLEVEL__=<val>** в режиме ``-gcc-version 930`` (по умолчанию) **<val>** равно **0**, в режиме ``-gcc-version 730`` **<val>** равно **0**, в режиме ``-gcc-version 550`` **<val>** равно **0**, в режиме ``-gcc-version 480`` **<val>** равно **0**, в режиме ``-gcc-version 440`` **<val>** равно **0**
* **__GNUG__=<val>** макрос взводится в режиме C++, **<val>** совпадает со значением макроса **__GNUC__**
* **__VERSION__=<val>** в режиме ``-gcc-version 930`` (по умолчанию) **<val>** равно **"9.3"**, в режиме ``-gcc-version 730`` **<val>** равно **"7.3"**, в режиме ``-gcc-version 550`` **<val>** равно **"5.5"**, в режиме ``-gcc-version 480`` **<val>** равно **"4.8"**, в режиме ``-gcc-version 440`` **<val>** равно **"4.4"**
* **__FINITE_MATH_ONLY__** в режиме ``-ffinite-math-only``
* **__GXX_EXPERIMENTAL_CXX0X__** в режимах C++11, C++14, C++17, C++20
* **__CHAR_UNSIGNED__** в режиме ``-funsigned-char``
* **__SIGNED_CHARS__** в режиме ``-fsigned-char`` (по умолчанию)
* **__SANITIZE_ADDRESS__** в режиме ``-fsanitize=address``
* **__pic__=<val>** взводится в режимах ``-fpic``, ``-fPIC``, ``-fpie``, ``-fPIE``. В режимах ``-fpic`` и ``-fpie`` **<val>** равно **1**, в остальных случаях **<val>** равно **2**
* **__PIC__=<val>** эквивалентно макросу **__pic__**
* **__pie__=<val>** взводится в режимах ``-fpie``, ``-fPIE``. В режиме ``-fpie`` **<val>** равно **1**, в остальных случаях **<val>** равно **2**
* **__PIE__=<val>** эквивалентно макросу **__pie__**
