Как объединить два строковых макроса в C? - PullRequest
2 голосов
/ 24 июня 2019

Я пытаюсь реализовать макрос VERSION для моей программы, который должен быть изменен при определенных обстоятельствах.

макрос VERSION определяется через Makefile (там помещается информация git) и является строкой. Теперь у меня есть набор ключей # define'd, и я хочу, чтобы VERSION отражал, какие из них включены. Теперь это выглядит следующим образом (main.h):

#define COMPLEX_DEPOSITION // This is switch. later in code it is used in #ifdef...#endif construction.

#ifdef COMPLEX_DEPOSITION
#define CD "_COMP_DEP" // this is the string I want to put in the end of VERSION
#define VERSION_ VERSION CD

#undef VERSION // this is to suppress 'macro redefinition' warning
#define VERSION VERSION_
#undef VERSION_
#endif

Ну, я получаю много ошибок, большинство из которых заставляют меня думать, что препроцессор C работает со строками в файле в случайном порядке: (

Позже у меня есть еще более сложная вещь, которая предназначена сделать VERSION -> VERSION_WLT_GAP_2

#define WIRESLIFETIMES

#ifdef WIRESLIFETIMES
#define GAP 2
#define VERSION_ (VERSION ## "_WLT_GAP_" ## #GAP)
#define VERSION VERSION_
#undef VERSION_
#endif

и я понятия не имел, что делать, и если это вообще возможно

Ответы [ 2 ]

3 голосов
/ 24 июня 2019

Строковые литералы объединяются естественным образом, когда располагаются рядом друг с другом.

"foo" "bar" совпадает с "foobar".

Что касается второго примера, вы, вероятно, захотите:

#define CAT_(A,B) A##B
#define CAT(A,B) CAT_(A,B)

#define GAP 2
#define VERSION CAT(VERSION_WLT_GAP_ , GAP)

VERSION //expands to VERSION_WLT_GAP_2

Я рекомендую немного поиграть с gcc -E / clang -E, чтобы узнать, как работают макросы, прежде чем пытаться составить из них что-нибудь сложное.

1 голос
/ 24 июня 2019

Ну, похоже, ответ следующий:

// /6571668/konkatenatsiya-makrosov-c-c
// 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)

// 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 STR(A) STRINGIZE_NX(A)


#define COMPLEX_DEPOSITION

#ifdef COMPLEX_DEPOSITION
#define CD "_COMPDEP"
#else
#define CD ""
#endif


#define WIRESLIFETIMES

#ifdef WIRESLIFETIMES
#define GAP 2
#define WLT STR(PPCAT(_WLT:G, GAP))
#define DISABLE_METROPOLIS
#else
#define WLT ""
#endif

#define VERSION VERSIONX CD WLT

, который производит V008.1-11-g68a9c89cb4-dirty_COMPDEP_WLT:G2, и я доволен этим.

Следует отметить, что я изменил -DVERSION=... на-DVERSIONX=... внутри Makefile

...