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

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

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

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

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

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

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

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

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

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

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

    $ 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__