EDIT
3.9.6 Довод Prescan
Макро аргументы полностью макро вспененные, прежде чем они подставляется в теле макрокоманды, если они не строковой или вставить с другими жетонами. После подстановки весь макрос, , включая замещенные аргументы, снова проверяется, чтобы макросы были . В результате аргументы дважды проверяются, чтобы развернуть в них макросы .
Макросы, которые вызывают другие макросы, которые строят или объединяются. Если аргумент является строковым или конкатенированным, предварительное сканирование не происходит. Если вы хотите развернуть макрос, то стройте или объедините его расширение , вы можете сделать это, заставив один макрос вызвать другой макрос , который выполняет строчение или конкатенацию.
Например, если у вас есть
#define AFTERX(x) X_ ## x
#define XAFTERX(x) AFTERX(x)
#define TABLESIZE 1024
#define BUFSIZE TABLESIZE
затем AFTERX (BUFSIZE) расширяется до X_BUFSIZE и XAFTERX (BUFSIZE) расширяется до X_1024. (Не X_TABLESIZE. Prescan всегда делает полное разложение.)
case1
#define JOIN__(lhs, rhs) lhs##rhs
=>, так как он имеет маркер оператора оклейки, это будет конкатенацией макро аргументы тех, которые не являются полностью макрорасширением перед тем, замещенным , ->, который является плохим способом расширения, и на первом месте мы не знаем, какие будут аргументы, которые ему будут переданы, он не будет ждать своего расширения, и он просто будет его конкатенацией.
следовательно, когда вы позвоните JOIN__(Foo, JOIN(A,B));
, он не позволит JOIN(A,B)
расшириться, и он будет соединять его с FOOJOIN (A, B).
Вариант 2 сейчас, с другой стороны, не #define JOIN_(lhs, rhs) JOIN__(lhs, rhs)
=> здесь, нет маркеров оператора вставки, Macro аргументов полностью макро вспененный, прежде чем они подставляются в тело макроса. следовательно, это позволит расширять lhs и rhs и вызывать с расширенными параметрами JOIN__(FOO,AB)
, поэтому теперь JOIN__ имеет оператор склейки маркеров, он просто объединяет его аргументы FOO и AB, то есть FOOAB. который является подходящим способом для этого.
CASE3 #define JOIN(lhs, rhs) JOIN_(lhs, rhs)
=> такой же, как CASE2.
Надеюсь, это объясняет причину парадигмы многоуровневого расширения.
ОРИГИНАЛ Оператор препроцессора ## обеспечивает способ объединения фактических аргументов во время макрорасширения. Если параметр в заменяемом тексте смещен рядом с ##, параметр заменяется фактическим аргументом, ## и окружающее пробел удаляются, а результат повторно просматривается. Например, макро-паста объединяет два аргумента:
#define paste(front, back) front ## back
so paste(name, 1) creates the token name1.
Я думаю, последний макрос 'JOIN __ (Foo, JOIN (A, B)); ' должен быть расширен как «FooJOIN (A, B)», а не только «FooJOIN», просим пояснить. –
Возможно. Я получаю предупреждение: неявное объявление функции «FooJOIN» недопустимо в C99', поэтому я не вижу, какие аргументы он получает. Но то, что вы говорите, имеет смысл. –