#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: 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)"
"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)
видає помилку.