Spec-Zone.ru › GCC 4 CPP

3.1 Макросы, подобные объектам

Макрос, подобный объекту, — это простой идентификатор, который будет заменён фрагментом кода. Он называется «подобным объекту», потому что он выглядит как объект данных в коде, который его использует. Они чаще всего используются для присвоения символических имён числовым константам.

Вы создаёте макросы с директивой ‘#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-4.9.4/cpp/Object-like-Macros.html

Spec-Zone.ru

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