#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
Препроцессор автоматически объединяет соседние строки.
РЕДАКТИРОВАТЬ:
Как отмечено ниже, конкатенацию выполняет не препроцессор, а компилятор.
L"a"
и "b"
получить L"ab"
, но можете объединить L"a"
и L"b"
получить L"ab"
.
Вам не нужно такое решение для строковых литералов, поскольку они объединяются на уровне языка, и это все равно не сработает, потому что «s» «1» не является допустимым токеном препроцессора.
[Изменить: в ответ на некорректный комментарий «Только для записи» ниже, который, к сожалению, получил несколько голосов, я повторю приведенное выше утверждение и замечу, что фрагмент программы
#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")
выдает это сообщение об ошибке на этапе предварительной обработки gcc: ошибка: вставка «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)"
"s""1"
действительно для C (и C ++). Это два токена (строковые литералы), которые компилятор объединяет и представляет собой один токен.
"s""1" isn't a valid token
- это правильно; это, как вы говорите, два жетона. Но объединение их вместе с помощью ## сделало бы их одним токеном предварительной обработки, а не двумя токенами, и поэтому компилятор не будет выполнять конкатенацию, а лексер отклонит их (язык требует диагностики).
STRINGIZE_NX(whatever occurs here)
расширяется до «все, что здесь происходит», независимо от любых макроопределений для того, что происходит или здесь.
if A is defined as FRED then STRINGIZE_NX(A) still expands to "FRED"
- это ложь и не имеет ничего общего с вашим тестом. Вы изо всех сил пытаетесь не понять или не понять это правильно, и я не собираюсь вам больше отвечать.
Подсказка: STRINGIZE
приведенный выше макрос хорош, но если вы допустили ошибку и его аргумент не является макросом - у вас есть опечатка в имени или вы забыли #include
файл заголовка - тогда компилятор с радостью поместит предполагаемое имя макроса в строка без ошибок.
Если вы хотите, чтобы аргумент STRINGIZE
всегда был макросом с нормальным значением C, тогда
#define STRINGIZE(A) ((A),STRINGIZE_NX(A))
расширит его один раз и проверит его на предмет действительности, отбросит его, а затем снова расширит в строку.
Мне потребовалось некоторое время, чтобы понять, почему в STRINGIZE(ENOENT)
итоге "ENOENT"
вместо "2"
... я не включил errno.h
.
,
оператора. :)
((1),"1") "." ((2),"2")
«1». «« 2 »)
STRINGIZE
определением "The value of ENOENT is " STRINGIZE(ENOENT)
работает, тогда как "The value of ENOENT is" STRINGIZE_EXPR(X)
выдает ошибку.