Язык Си



Макроподстановка - часть 2


вызовет увеличение i и j дважды. Кроме того, следует позаботиться о скобках, чтобы обеспечить нужный порядок вычислений. Задумайтесь, что случится, если при определении

#define square(x) x*x /* НЕВЕРНО */

вызвать square (z+1).

Тем не менее макросредства имеют свои достоинства. Практическим примером их использования является частое применение getchar и putchar из <stdio.h>, реализованных с помощью макросов, чтобы из6ежать расходов времени от вызова функции на каждый обрабатываемый символ. Функции в <ctype.h> обычно также реализуются с помощью макросов. Действие #define можно отменить с помощью #undef:

#undef getchar int getchar(void) {...}

Как правило, это делается, чтобы заменить макроопределение настоящей функцией с тем же именем.

Имена формальных параметров не заменяются, если встречаются в заключенных в кавычки строках. Однако, если в замещающем тексте перед формальным параметром стоит знак #, этот параметр будет заменен на аргумент, заключенный в кавычки. Это может сочетаться с конкатенацией (склеиванием) строк, например, чтобы создать макрос отладочного вывода:

#define dprint(expr) printf(#expr " = %g\n", expr)

Обращение к

dprint(x/y);

развернется в

printf("x/y" " = %g\n", x/y);

а в результате конкатенации двух соседних строк получим

printf("x/y=%g\n", x/y);

Внутри фактического аргумента каждый знак " заменяется на \", а каждая \ на \\, так что результат подстановки приводит к правильной символьной константе.

Оператор ## позволяет в макрорасширениях конкатенировать аргументы. Если в замещающем тексте параметр соседствует с ##, то он заменяется соответствующим ему аргументом, а оператор ## и окружающие его символы-разделители выбрасываются. Например, в макроопределении paste конкатенируются два аргумента

#define paste(front, back) front ## back

так что paste(name, 1) сгенерирует имя name1.

Правила вложенных использований оператора ## не определены; другие подробности, относящиеся к ##, можно найти в .

Упражнение 4.14. Определите swap(t,x,y) в виде макроса, который осуществляет обмен значениями указанного типа t между аргументами x и y. (Примените блочную структуру.)




Содержание  Назад  Вперед