Использование аргументов с #define
Во избежание ошибок при вычислении выражений параметры макроопределения необходимо заключать в скобки.
#define идентификатор1 (идентификатор2, . . .) строка
Пример:
#define abs(A) (((A) > 0)?(A) : -(A))
Каждое вхождение выражения abs(arg) в тексте программы заменяется на
((arg) > 0) ? (arg) : -(arg),
причем параметр макроопределения А заменяется на arg.
Пример:
#define nmem (P,N)\ (P) -> p_mem[N].u_long
Символ \ продолжает макроопределение на вторую строчку. Это макроопределение уменьшает сложность выражения, описывающего массив объединений внутри структуры.
Макроопределение с аргументами очень похоже на функцию, поскольку аргументы его заключены в скобки:
/* макроопределение с аргументами */ #define SQUARE(x) x*x #define PR(x) printf("x равно %d.\n", x) main( ) { int x = 4; int z; z = SQUARE(x); PR(z); z = SQUARE(2); PR(z); PR(SQUARE(x)); PR(SQUARE(x+2)); PR(100/SQUARE(2)); PR(SQUARE(++x)); }
Всюду, где в нашей программе появляется макроопределение SQUARE(x), оно заменяется на x*x . В отличие от наших прежних примеров, при использовании этого макроопределения мы можем совершенно свободно применять символы, отличные от x. В макроопределении 'x' замещается символом, использованным в макровызове программы. Поэтому макроопределение SQUARE(2) замещается на 2*2. Таким образом, x действует как аргумент. Однако, аргумент макроопределения не работает - точно так же, как аргумент функции. Вот результаты выполнения программы:
z равно 16. z равно 4. SQUARE(x) равно 16. SQUARE(x+2) равно 14. 100/SQUARE(2) равно 100. SQUARE(++x) равно 30.
printf("SQUARE(x) равно %d.\n",x*x);
и выводит на печать
SQUARE(x) равно x*x.
Если макроопределение включает аргумент с двойными кавычками, то аргумент будет замещаться строкой из макровызова. Но после этого он в дальнейшем не расширяется, даже если строка является еще одним макроопределением. В нашем примере переменная x стала макроопределением SQUARE(x) и осталась им. Вспомним, что x=4. Это позволяет предположить, что SQUARE(x+2) будет равно 6*6 или 36. Но напечатанный результат говорит, что получается число 14. Причина такого результата такова: препроцессор не делает вычислений. Он только замещает строку. Всюду, где наше определение указывает на x, препроцессор подставит строку x+2.
Таким образом,
x*x становится x+2*x+2
Если x равно 4, то получается
4+2*4+2=4+8+2=14
Вызов функции передает значение аргумента в функцию во время выполнения программы. Макровызов передает строку аргументов в программу до ее компиляции.