Вы не можете этого сделать, если USER определен как строка в кавычках.
Но вы можете это сделать, если ПОЛЬЗОВАТЕЛЬ - это просто ДЖЕК, КОРОЛЕВА, Джокер или что-то еще.
Есть два приема:
- Соединение токенов, при котором вы объединяете идентификатор с другим идентификатором, просто объединяя их символы. Это позволяет сравнивать с JACK, не прибегая
#define JACK
к чему-либо.
- вариативное расширение макроса, которое позволяет вам обрабатывать макросы с переменным числом аргументов. Это позволяет вам расширять определенные идентификаторы до различного количества запятых, которые станут вашим сравнением строк.
Итак, начнем с:
#define JACK_QUEEN_OTHER(u) EXPANSION1(ReSeRvEd_, u, 1, 2, 3)
Теперь, если я напишу JACK_QUEEN_OTHER(USER)
, а USER будет JACK, препроцессор превратит это вEXPANSION1(ReSeRvEd_, JACK, 1, 2, 3)
Шаг второй - конкатенация:
#define EXPANSION1(a, b, c, d, e) EXPANSION2(a##b, c, d, e)
Теперь JACK_QUEEN_OTHER(USER)
становитсяEXPANSION2(ReSeRvEd_JACK, 1, 2, 3)
Это дает возможность добавить несколько запятых в зависимости от того, соответствует ли строка:
#define ReSeRvEd_JACK x,x,x
#define ReSeRvEd_QUEEN x,x
Если ПОЛЬЗОВАТЕЛЬ - ДЖЕК, JACK_QUEEN_OTHER(USER)
становитсяEXPANSION2(x,x,x, 1, 2, 3)
Если ПОЛЬЗОВАТЕЛЬ - КОРОЛЕВА, JACK_QUEEN_OTHER(USER)
становитсяEXPANSION2(x,x, 1, 2, 3)
Если USER другой, JACK_QUEEN_OTHER(USER)
становитсяEXPANSION2(ReSeRvEd_other, 1, 2, 3)
В этот момент произошло нечто критическое: четвертый аргумент макроса EXPANSION2 равен 1, 2 или 3, в зависимости от того, был ли передан исходный аргумент валетом, дамой или чем-то еще. Так что все, что нам нужно сделать, это выбрать его. По многим причинам нам понадобятся два макроса для последнего шага; это будут EXPANSION2 и EXPANSION3, даже если один кажется ненужным.
Собирая все вместе, у нас есть эти 6 макросов:
#define JACK_QUEEN_OTHER(u) EXPANSION1(ReSeRvEd_, u, 1, 2, 3)
#define EXPANSION1(a, b, c, d, e) EXPANSION2(a##b, c, d, e)
#define EXPANSION2(a, b, c, d, ...) EXPANSION3(a, b, c, d)
#define EXPANSION3(a, b, c, d, ...) d
#define ReSeRvEd_JACK x,x,x
#define ReSeRvEd_QUEEN x,x
И вы можете использовать их так:
int main() {
#if JACK_QUEEN_OTHER(USER) == 1
printf("Hello, Jack!\n");
#endif
#if JACK_QUEEN_OTHER(USER) == 2
printf("Hello, Queen!\n");
#endif
#if JACK_QUEEN_OTHER(USER) == 3
printf("Hello, who are you?\n");
#endif
}
Обязательная ссылка на Godbolt: https://godbolt.org/z/8WGa19