====== препроцессор ======
Препроцессор имеет следующие директивы:
* ''#define'' - определяет макрос или препроцессорный идентификатор
* ''#undef'' - отменяет определение макроса или идентификатора
* ''#ifdef'' - проверяет, определен ли идентификатор
* ''#ifndef'' - проверяет неопределенность идентификатора
* ''#include'' - включает текст из файла
* ''#if'' - проверяет условие выражения (как условная конструкция if)
* ''#else'' - задает альтернативное условие для #if
* ''#endif'' - окончание условной директивы #if
* ''#elif'' - задает альтернативное условие для #if
* ''#line'' - меняет номер следующей ниже строки
* ''#error'' - формирует текст сообщения об ошибке трансляции
* ''#pragma'' - определяет действия, которые зависят от конкретной реализацией компилятора
* ''#'' - пустая директива, по сути ничего не делает
===== макросы =====
^ Компилятор ^ Макрос ^
| Borland | %%__BORLANDC__%% |
| Clang | %%__clang__%% |
| Codeplay VectorC | %%__VECTORC__%% |
| Digital Mars | %%__DMC__%% |
| Gnu | %%__GNUC__%% |
| Intel legacy “Classic” | %%__INTEL_COMPILER__%% |
| Intel LLVM based | %%__INTEL_LLVM_COMPILER__%% |
| Microsoft | %%_MSC_VER%% |
| Pathscale | %%__PATHSCALE__%% |
| Symantec | %%__SYMANTECC__%% |
| Watcom | %%__WATCOMC__%% |
^ Архитектура ^ Макрос ^
| x86 | %%_M_IX86%%, %%__INTEL__%%, %%__i386__%% |
| x86-64 | %%_M_X64%%, %%__x86_64__%%, %%__amd64__%% |
| IA64 | %%__IA64__%% |
| DEC Alpha | %%__ALPHA__%% |
| Motorola Power PC | %%__POWERPC__%% |
^ Архитектура ^ Макрос ^
| Any little endian | %%__LITTLE_ENDIAN__%% |
| Any big endian | %%__BIG_ENDIAN__%% |
^ Операционная система ^ Макрос ^
| DOS 16 bit | %%__MSDOS__%%, %%_MSDOS%% |
| Windows 16 bit | %%_WIN16%% |
| Windows 32 bit | %%_WIN32%%, %%__WINDOWS__%% |
| Windows 64 bit | %%_WIN64%%, %%_WIN32%% |
| Cygwin | %%__CYGWIN__%% |
| Mingw | %%__MINGW32__%%, %%__MINGW64__%% |
| Linux 32 bit | %%__unix__%%, %%__linux__%% |
| Linux 64 bit | %%__unix__%%, %%__linux__%%, %%__LP64__%%, %%__amd64__%% |
| BSD | %%__unix__%%, %%__BSD__%%, %%__FREEBSD__%% |
| Mac OS | %%__APPLE__%%, (%%__DARWIN__%%, %%__MACH__%%) |
| OS/2 | %%__OS2__%% |
===== #define =====
определяет идентификатор и последовательность символов, которые будут подставляться вместо идентификатора каждый раз, когда он встретится в исходном файле
#include
#define BEGIN {
#define END }
#define N 23
#define ADD(a,b) (a+b)
int main(void)
BEGIN
int x = N;
printf("Number: %d", x); // Number: 23
printf("%d + %d = %d", 10, 5, ADD(10, 5)); // 10 + 5 = 15
return 0;
END
Следует учитывать, что директива препроцессор **не** заменяет последовательности символов в двойных и одинарных кавычках и в комментариях
++++NTB|
Макрос можно определять в компиляторе, например ''gcc -D ИЛЕНТИФКАТОР=ЗНАЧЕНИЕ''
++++
===== #undef =====
undef отменяет действие макроcа define
#include
#define STRING "Good morning \n"
int main(void) {
printf(STRING);
#undef STRING
#define STRING "Good afternoon \n"
printf(STRING);
#undef STRING
#define STRING "Good evening \n"
printf(STRING);
return 0;
}
===== #ifdef =====
Директива #ifdef проверяет, определен ли идентификатор. Если он определен, выполняется соответствующий код.
#include
#define FEATURE_ENABLED
int main(void) {
#ifdef FEATURE_ENABLED
printf("Feature is enabled.\n"); // Этот код будет выполнен
#else
printf("Feature is disabled.\n");
#endif
return 0;
}
Если `FEATURE_ENABLED` будет отменен, код в первом блоке не выполнится.
===== #ifndef =====
работает аналогично #ifdef, но проверяет ложность уловия
===== #include =====
Эта директива подключает в исходный текст указанного файла.
#include <имя_файла> // поиск файла в стандартных системных каталогах
#include "имя_файла" // поиск файла в директории с заголовочниками (определено компилятором)
++++NTB|
Вообще есть стандартный набор встроенных заголовочных файлов, который определяется стандартом языка
* ''assert.h'' - отвечает за диагностику программ
* ''complex.h'' - для работы с комплексными числами
* ''ctype.h'' - отвечает за преобразование и проверку символов
* ''errno.h'' - отвечает за проверку ошибок
* ''fenv.h'' - для доступа к окружению, которое управляет операциями с числами с плавающей точкой
* ''float.h'' - отвечает за работу с числами с плавающей точкой
* ''inttypes.h'' - для работы с большими целыми числами
* ''iso646.h'' - содержит ряд определений, которые расширяют ряд логических операций
* ''limits.h'' - содержит предельные значения целочисленных типов
* ''locale.h'' - отвечает за работу с локальной культурой
* ''math.h'' - для работы с математическими выражениями
* ''setjmp.h'' - определяет возможности нелокальных переходов
* ''signal.h'' - для обработки исключительных ситуаций
* ''stdalign.h'' - для выравнивания типов
* ''stdarg.h'' - обеспечивает поддержку переменного числа параметров
* ''stdatomic.h'' - для выполнения атомарных операций по разделяемым данным между потоками
* ''stdbool.h'' - для работы с типом _Bool
* ''stddef.h'' - содержит ряд вспомогательных определений
* ''stdint.h'' - для работы с целыми числами
* ''stdio.h'' - для работы со средствами ввода-вывода
* ''stdlib.h'' - содержит определения и прототипы функций общего пользования
* ''stdnoreturn.h'' - содержит макрос noreturn
* ''string.h'' - для работы со строками
* ''tgmath.h'' - подключает math.h и complex.h плюс добавляет дополнительные возможности по работе с математическими вычислениями
* ''threads.h'' - для работы с потоками
* ''time.h'' - для работы с датами и временем
* ''uchar.h'' - для работы с символами в кодировке Unicode
* ''wchar.h'' - для работы с символами
* ''wctype.h'' - содержит дополнительные возможности для работы с символами
++++
===== #if =====
Директива #if проверяет условие выражения, аналогично конструкции ''if'' в языке C.
#include
#define VERSION 2
int main(void) {
#if VERSION == 1
printf("Version 1\n");
#elif VERSION == 2
printf("Version 2\n"); // Этот код будет выполнен
#else
printf("Unknown version\n");
#endif
return 0;
}
===== #else =====
Директива #else задает альтернативное условие для директивы #if. Если предыдущее условие не было выполнено, выполняется код под **#else**.
===== #endif =====
Директива #endif завершает условную блокировку, начатую с #if, #ifdef или #ifndef.
===== #elif =====
Директива #elif позволяет задавать дополнительные условия в цепочке условных проверок, что обеспечивает удобство структурирования кода.
===== #line =====
Директива #line позволяет изменять номер строки и имя файла для отчетов об ошибках, которые выводит компилятор.
#include
#line 100 "custom_file.c" // Устанавливает номер строки и имя файла
int main(void) {
printf("Hello from line %d of %s\n", __LINE__, __FILE__);
return 0;
}
===== #error =====
Директива #error заставляет компилятор выдавать сообщение об ошибке и завершать процесс компиляции.
#include
#ifndef REQUIRED_FEATURE
#error "Required feature is not defined!"
#endif
int main(void) {
printf("Program runs successfully.\n");
return 0;
}
===== #pragma =====
Директива #pragma используется для передачи специальных инструкций компилятору. Эти инструкции __зависят от конкретного компилятора__ и могут варьироваться.
#include
#pragma message("Compiling the program...") // Выводит сообщение во время компиляции
int main(void) {
printf("Hello, World!\n");
return 0;
}
===== # =====
Пустая директива # не выполняет никаких действий, но может использоваться для организации или форматирования кода.