3.3 Аргументы макроса
Макросы, подобные функциям, могут принимать аргументы, как и обычные функции. Для определения макроса, использующего аргументы, вводится список параметров между парой скобок в определении макроса, превращающего его в функцию. Параметры должны быть допустимыми идентификаторами языка C, разделенными запятыми и необязательными пробелами.
Для вызова макроса, принимающего аргументы, записывается имя макроса, за которым следует список фактических аргументов в скобках, разделенных запятыми. Вызов макроса не ограничен одной логической строкой — он может охватывать любое количество строк в исходном файле. Количество аргументов должно соответствовать количеству параметров в определении макроса. При раскрытии макроса каждое использование параметра в его теле заменяется токенами соответствующего аргумента. (Вы можете не использовать все параметры в теле макроса.)
В качестве примера, ниже представлен макрос, вычисляющий минимум из двух числовых значений, как это определено во многих программах на C, и некоторые примеры его использования.
#define min(X, Y) ((X) < (Y) ? (X) : (Y)) x = min(a, b); → x = ((a) < (b) ? (a) : (b)); y = min(1, 2); → y = ((1) < (2) ? (1) : (2)); z = min(a + 28, *p); → z = ((a + 28) < (*p) ? (a + 28) : (*p));
(В этом небольшом примере вы уже можете увидеть несколько опасностей использования аргументов макроса. Подробные объяснения см. в разделе Ошибки при использовании макросов.)
Пробелы в начале и конце каждого аргумента отбрасываются, а все пробелы между токенами аргумента сводятся к одному пробелу. Скобки внутри каждого аргумента должны быть сбалансированы; запятая внутри таких скобок не завершает аргумент. Однако нет требования о балансировке квадратных скобок или фигурных скобок, и они не препятствуют запятой разделять аргументы. Таким образом,
macro (array[x = y, x + 1])
передает два аргумента макросу macro: array[x = y и x +
1]. Если вы хотите предоставить array[x = y, x + 1] в качестве аргумента, вы можете написать его как array[(x = y, x + 1)], что эквивалентно коду на C.
Все аргументы макроса полностью раскрываются макросами до того, как подставляются в тело макроса. После подстановки весь текст снова сканируется на наличие макросов для раскрытия, включая аргументы. Это правило может показаться странным, но оно тщательно разработано, чтобы вам не нужно было беспокоиться о том, является ли какой-либо вызов функции фактически вызовом макроса. Однако вы можете столкнуться с проблемами, если попытаетесь проявить излишнюю хитрость. Подробное обсуждение см. в разделе Предварительный просмотр аргументов.
Например, min (min (a, b), c) сначала раскрывается до
min (((a) < (b) ? (a) : (b)), (c))
а затем до
((((a) < (b) ? (a) : (b))) < (c) ? (((a) < (b) ? (a) : (b))) : (c))
(Перевод строки, показанный здесь для ясности, на самом деле не будет сгенерирован.)
Вы можете оставить аргументы макроса пустыми; это не ошибка для препроцессора (но многие макросы при этом раскроются в недопустимый код). Вы не можете полностью пропустить аргументы; если макрос принимает два аргумента, то на верхнем уровне списка аргументов должна быть ровно одна запятая. Вот несколько забавных примеров, использующих min:
min(, b) → (( ) < (b) ? ( ) : (b)) min(a, ) → ((a ) < ( ) ? (a ) : ( )) min(,) → (( ) < ( ) ? ( ) : ( )) min((,),) → (((,)) < ( ) ? ((,)) : ( )) min() error→ macro "min" requires 2 arguments, but only 1 given min(,,) error→ macro "min" passed 3 arguments, but takes just 2
Пробел не является токеном препроцессинга, поэтому, если макрос foo принимает один аргумент, foo () и foo ( ) оба передают ему пустой аргумент. Предыдущие реализации и документация GNU препроцессора ошибались в этом отношении, настаивая на том, что функционоподобному макросу, принимающему один аргумент, должен передаваться пробел, если требуется пустой аргумент.
Параметры макроса, встречающиеся внутри строковых литералов, не заменяются соответствующими фактическими аргументами.
#define foo(x) x, "x" foo(bar) → bar, "x"
Далее: Строковая подстановка, Предыдущее: Макросы, подобные функциям, Наверх: Макросы [Содержание][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-6.5.0/cpp/Macro-Arguments.html