Spec-Zone.ru › GCC 6 CPP

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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API