1.8 Препроцессор
Препроцессор это часть языка С. Препроцессор считывает исходный код, отвечает на размещенные в нем директивы и производит модифицированную версию этого исходного кода, которая передаётся компилятору. Подстановки препроцессором выполняются рекурсивно, т.е выполняется многопроходная обработка.
- Определение/удаление макроса. Макрос может быть определён без значения и может использоваться в качестве проверяемого флага.
#define VAL_T 345
#undef VAL_T
#define VAL_T 234
- Для перевода на другую строку используется ";\" :
#define FILLSCREAN(color) _AX = 0x0600;\
_CX = 0x0000;\
_DX = 0x184f;\
_BH = color;\
geninterrupt(0x10);
- Использование параметров:
#define min(a,b) ((a) < (b) ? (a) : (b))
result = min(44,uplimit);
// result = ((44) < (uplimit) ? (44) : (uplimit));
- Для объединения формальных параметров используются символы ##:
#define var( i , j ) ( i##j ) // var( x , 6 ) = x6
- Для преобразования фактического параметра в строку используется символ # который помещается перед формальным макропараметром:
#define TRACE(flag) printf(#flag "=%d\n", flag)
#define err(...) fprintf(stderr,__VA_ARGS__)
err("%s %d\n","The error code ",48);
// fprintf(stderr,"%s %d\n","The error code ",48);
#define errout(a,b,...) \
fprintf(stderr,"File %s Line %d\n",a,b); \
fprintf(stderr,__VA_ARGS__)
errout(__FILE__,__LINE__,"Unexpected termination\n");
1.8.1 Директивы Препроцессора
_Pragma
_Pragma("GCC poison printf")
Оператор для вызова прагмы из тела макроса (табл.7).
#define
#define ident ident1;
Заменяет все последующие определения <ident> на лексему <ident1> (совокупность лексем).
#elif, #if
#if expresion
#elif expresion1
#endif
Проверяет выражение <expresion>, связанное с директивами #if, или #elif , если выражение истинно (отличный от нуля), то выполняются следующие строки до директив условия или конца условий. Директива #elif является объединением директив #else и #if. Если имеется #else, то нижестоящие строки выполняются когда выражение в #if или #elif имеет нулевое значение. Нельзя использовать в качестве условия оператор sizeof, составные типы, float или enum типы.
defined
#if defined(VAR)
#elif !defined(NVAR)
#endif
Оператор проверки определённости, используется в паре с #if.
#else
Нижестоящие строки выполняются если выражение в #if, #ifdef, #ifndef или #elif имеет нулевое значение.
#endif
Указывает на конец условия.
#error
#error сообщение
Генерация сообщения ошибки на stderr и завершения процесса компиляции.
#ifdef
#ifdef <identifier>
Выполняет последующие строки до #endif, если <identifier> был ранее определен.
#ifndef
#ifndef <identifier>
Выполняет последующие строки до #endif, если <identifier> не был ранее определён.
#include
#include <filename>
Вставляет содержимое файла <filename> в текущий файл. Если путь к имени файла включен в двойные кавычки ,то поиск осуществляется внутри текущего каталога.
#include_next
#include_next <filename>
?
#line
#line n file
Изменяет внутренний номер строки компилятора на <n>, а также изменяет внутреннее имя файла на <file>. Текущий номер строки и имя файла доступны через константы препроцессора __LINE__ и __FILE__.
#pragma
#pragma directives
Инструктирует компилятор, о выполнение машинно-специфических возможностей, определенных параметром <directives> (таблица [*]).
#undef
#undef identifier
Удаляет текущее определение <identifier>, который был предварительно определен директивой #define.
#warning
#warning сообщение
Генерация сообщения предупреждения на stderr и продолжение компиляции.
Таблица 7.
Параметры директивы pragma, препроцессора
Имя | Назначение |
pack | Определяет, как компилятор выравнивает данные при сохранении в памяти. Может также использоваться с, вталкиванием и выталкиванием параметров.
#pragma pack(n) #pragma pack(push, n) #pragma pack(pop)
|
Таблица 8.
Предопределённые символьные константы
Имя | Назначение |
__BASE_FILE__ | Полный путь к каталогу исходного файла. |
__CHAR_UNSIGNED__ | Указывает на то, что символьный тип является безнаковым. |
__cplusplus | Указывает на то, что исходный код является программой на языке С++. |
__DATE__ | Дата компиляции исходного файла (строка). |
__FILE__ | Имя исходного файла (строка). |
__func__ | Имя текущей функции. |
__FUNCTION__ | Имя текущей функции. |
__PRETTY_FUNCTION__ | Полное имя текущей функции. Для C++ включает имена классов. |
__INCLUDE_LEVEL__ | Глубина включения (include) файла. |
__LINE_ | Номер текущей строки исходного текста (целое число). |
__NO_INLINE__ | Указывает на отсутствие inline-функций. |
__OBJC__ | Программа на языке Objective-C. |
__OPTIMIZE__ | Указывает на то, что назначен уровень оптимизации. |
__OPTIMIZE_SIZE__ | Оптимизация размера программы. |
__STDC__ | Компилятор соответствует правилам стандарта языка C. |
__TIME__ | Время компиляции исходного файла (строка). |
__VERSION__ | Полный номер версии. |