Конкатенация макросов C / C ++ - PullRequest
103 голосов
/ 10 марта 2011
#define STR1      "s"
#define STR2      "1"
#define STR3      STR1 ## STR2

Можно ли объединить STR3 == "s1"? Вы можете сделать это, передав аргументы в другую функцию Macro. Но есть ли прямой путь?

Ответы [ 3 ]

134 голосов
/ 10 марта 2011

Если они обе строки, вы можете просто сделать:

#define STR3 STR1 STR2

Препроцессор автоматически объединяет смежные строки.

EDIT:

Как отмечено ниже, конкатенация выполняет не препроцессор, а компилятор.

93 голосов
/ 10 марта 2011

Вам не нужно такое решение для строковых литералов, так как они объединены на уровне языка, и это не сработает в любом случае, потому что "s" "1" не является допустимым токеном препроцессора. Однако для общего вставки токена попробуйте следующее:

/*
 * Concatenate preprocessor tokens A and B without expanding macro definitions
 * (however, if invoked from a macro, macro arguments are expanded).
 */
#define PPCAT_NX(A, B) A ## B

/*
 * Concatenate preprocessor tokens A and B after macro-expanding them.
 */
#define PPCAT(A, B) PPCAT_NX(A, B)

Затем, например, PPCAT(s, 1) создает идентификатор s1.

Продолжаем тему следующих макросов:

/*
 * Turn A into a string literal without expanding macro definitions
 * (however, if invoked from a macro, macro arguments are expanded).
 */
#define STRINGIZE_NX(A) #A

/*
 * Turn A into a string literal after macro-expanding it.
 */
#define STRINGIZE(A) STRINGIZE_NX(A)

Тогда

#define T1 s
#define T2 1
STRINGIZE(PPCAT(T1, T2)) // produces "s1"
23 голосов
/ 08 февраля 2012

Подсказка: приведенный выше макрос STRINGIZE - это круто, но если вы допустили ошибку и его аргумент не является макросом - в названии была опечатка или вы забыли #include файл заголовка - тогда компилятор с радостью поместит предполагаемое имя макроса в строку без ошибок.

Если вы намереваетесь, что аргументом STRINGIZE всегда является макрос с нормальным значением C, тогда

#define STRINGIZE(A) ((A),STRINGIZE_NX(A))

развернет его один раз и проверит на правильность, откажется от него, а затем снова развернет в строку.

Мне потребовалось некоторое время, чтобы выяснить, почему STRINGIZE(ENOENT) заканчивал как "ENOENT" вместо "2" ... Я не включил errno.h.

...