#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
Можно ли конкатенатировать STR3 == "s1"? Вы можете сделать это, передав аргументы другой функции макроса. Но есть ли прямой путь?
#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
Можно ли конкатенатировать STR3 == "s1"? Вы можете сделать это, передав аргументы другой функции макроса. Но есть ли прямой путь?
Если это обе строки, вы можете просто:
#define STR3 STR1 STR2
Препроцессор автоматически объединяет соседние строки.
EDIT:
Как отмечено ниже, это не препроцессор, а компилятор, который выполняет конкатенацию.
Вам не нужно такое решение для строковых литералов, поскольку они объединяются на уровне языка, и в любом случае оно не будет работать, потому что "s" "1" не является допустимым токеном препроцессора.
[Редактировать: В ответ на неправильный комментарий "Только для записи" ниже, который, к сожалению, получил несколько голосов, я повторю приведенное выше утверждение и заметлю, что фрагмент программы
#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")
выдает это сообщение об ошибке на этапе предварительной обработки gcc: error: вставка "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_NX(s, 1)
и PPCAT(s, 1)
генерируют идентификатор s1
, если s
не определен как макрос, и в этом случае PPCAT(s, 1)
выдает <macro value of s>1
.
Продолжаем тему следующих макросов:
/*
* 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"
В отличие от
STRINGIZE(PPCAT_NX(T1, T2)) // produces "T1T2"
STRINGIZE_NX(PPCAT_NX(T1, T2)) // produces "PPCAT_NX(T1, T2)"
#define T1T2 visit the zoo
STRINGIZE(PPCAT_NX(T1, T2)) // produces "visit the zoo"
STRINGIZE_NX(PPCAT(T1, T2)) // produces "PPCAT(T1, T2)"
Подсказка: макрос STRINGIZE
- это классно, но если вы допустили ошибку, а его аргумент не является макросом - у вас была опечатка в имени или забыли #include
заголовочный файл - тогда компилятор будет счастливо помещать имя якобы макроса в строку без ошибок.
Если вы предполагаете, что аргумент STRINGIZE
всегда является макросом с нормальным значением C, тогда
#define STRINGIZE(A) ((A),STRINGIZE_NX(A))
будет расширять его один раз и проверять его на достоверность, отменить это, а затем развернуть его снова в строку.
Мне потребовалось некоторое время, чтобы понять, почему STRINGIZE(ENOENT)
заканчивается как "ENOENT"
вместо "2"
... Я не включил errno.h
.