3.1 Макросы, подобные объектам
Макрос, подобный объекту — это простой идентификатор, который будет заменён фрагментом кода. Он называется «подобным объекту», потому что в коде, использующем его, он выглядит как объект данных. Они чаще всего используются для присвоения символических имён числовым константам.
Вы создаёте макросы с помощью директивы «#define». За директивой «#define» следует имя макроса, а затем последовательность токенов, для которой он должен быть сокращением; это также называют телом, расширением или списком замены макроса. Например,
#define BUFFER_SIZE 1024
определяет макрос с именем BUFFER_SIZE как сокращение для токена 1024. Если где-то после этой директивы «#define» есть оператор C в виде
foo = (char *) malloc (BUFFER_SIZE);
то препроцессор C распознает и расширит макрос BUFFER_SIZE. Компилятор C увидит те же токены, что и если бы вы написали
foo = (char *) malloc (1024);
По соглашению, имена макросов записываются заглавными буквами. Программы легче читать, когда с первого взгляда можно определить, какие имена являются макросами.
Тело макроса заканчивается в конце строки «#define». При необходимости определение можно продолжить на нескольких строках, используя обратную косую черту и перевод строки. Однако при расширении макроса всё будет выведено в одной строке. Например,
#define NUMBERS 1, \
2, \
3
int x[] = { NUMBERS };
→ int x[] = { 1, 2, 3 };
Наиболее распространённым видимым следствием этого являются неожиданные номера строк в сообщениях об ошибках.
Нет ограничений на то, что может находиться в теле макроса, при условии, что оно разлагается на допустимые токены препроцессирования. Скобки не должны сбалансироваться, а тело необязательно должно выглядеть как допустимый код C. (Если этого нет, вы можете получить сообщения об ошибках от компилятора C при использовании макроса.)
Препроцессор C сканирует вашу программу последовательно. Определения макросов вступают в силу в том месте, где вы их пишете. Таким образом, следующий вход в препроцессор C
foo = X; #define X 4 bar = X;
производит
foo = X; bar = 4;
При расширении препроцессором имени макроса расширение макроса заменяет вызов макроса, затем расширение проверяется на наличие других макросов для расширения. Например,
#define TABLESIZE BUFSIZE
#define BUFSIZE 1024
TABLESIZE
→ BUFSIZE
→ 1024
TABLESIZE сначала расширяется, чтобы получить BUFSIZE, затем этот макрос расширяется, чтобы получить окончательный результат 1024.
Обратите внимание, что BUFSIZE не было определено, когда было определено TABLESIZE. Директива «#define» для TABLESIZE использует точно указанное расширение — в данном случае BUFSIZE — и не проверяет, содержит ли оно имена макросов. Только когда вы используете TABLESIZE, результат его расширения сканируется на наличие других имён макросов.
Это имеет значение, если вы измените определение BUFSIZE в какой-то точке исходного файла. TABLESIZE, определённое, как показано, всегда будет расширяться, используя определение BUFSIZE, которое в данный момент действует:
#define BUFSIZE 1020 #define TABLESIZE BUFSIZE #undef BUFSIZE #define BUFSIZE 37
Теперь TABLESIZE расширяется (в два этапа) до 37.
Если расширение макроса содержит собственное имя, либо непосредственно, либо через промежуточные макросы, оно не расширяется повторно при проверке расширения на наличие других макросов. Это предотвращает бесконечную рекурсию. См. Макросы, ссылающиеся на себя для получения подробных сведений.
Далее: Функционально-подобные макросы, Назад: Макросы [Оглавление][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-8.5.0/cpp/Object-like-Macros.html