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-9.5.0/cpp/Object-like-Macros.html