Как именно работает трюк с двойной строкой?
по крайней мере, некоторых C препроцессоры позволяют вам строчить значение макроса, а не его имя, передавая его через один функциональный макрос другому, который его строчит:
#define STR1(x) #x
#define STR2(x) STR1(x)
#define THE_ANSWER 42
#define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */
пример использования здесь.
Это действительно работает, по крайней мере, в GCC и Clang (оба с -std=c99
), но я не уверена как он работает в C-стандартных условиях.
это поведение гарантируется C99?
Если да, то как работает C99 гарантировать это?
Если нет, то в какой момент поведения с определенными Оук-определенными?
2 ответа:
Да, это гарантировано.
это работает, потому что аргументы макросов сами макро-расширены,кроме где имя аргумента макроса отображается в теле макроса со строковым символом # или маркером-Пастером ##.
6.10.3.1/1:
... После аргументов в пользу вызов функционального макроса были идентифицированы, аргумент происходит подмена. Параметр в списке замены, если предшествует # или ## предварительная обработка маркер или за ним следует ## токен предварительной обработки (см. ниже), является заменяется соответствующим аргументом ведь все содержащиеся в нем макросы были расширены...
Так что, если вы делаете
STR1(THE_ANSWER)
тогда вы получаете "THE_ANSWER", потому что аргумент STR1 не является макрорасширенным. Однако аргумент STR2 и макрос расширяется, когда он подставляется в определение STR2, что, следовательно, дает STR1 аргумент42
, в результате из "42".
Как отмечает Стив, это гарантировано, и это было гарантировано с тех пор, как стандарт C89 - это был стандарт, кодифицированный # и ## операторы в макросах и мандаты рекурсивно расширяют макросы в args перед их заменой в теле тогда и только тогда, когда тело не применяет # или ## аргумент. C99 в этом отношении не отличается от C89.