Você não pode fazer isso se USER for definido como uma string entre aspas.
Mas você pode fazer isso se USER for apenas JACK ou QUEEN ou Joker ou o que for.
Existem dois truques para usar:
- Splicing de token, onde você combina um identificador com outro identificador apenas concatenando seus caracteres. Isso permite que você compare com o JACK sem ter que
#define JACK
fazer nada
- expansão variável de macro, que permite lidar com macros com números variáveis de argumentos. Isso permite que você expanda identificadores específicos em vários números de vírgulas, que se tornarão sua comparação de strings.
Então, vamos começar com:
#define JACK_QUEEN_OTHER(u) EXPANSION1(ReSeRvEd_, u, 1, 2, 3)
Agora, se eu escrever JACK_QUEEN_OTHER(USER)
e USER for JACK, o pré-processador transformará isso emEXPANSION1(ReSeRvEd_, JACK, 1, 2, 3)
A segunda etapa é a concatenação:
#define EXPANSION1(a, b, c, d, e) EXPANSION2(a##b, c, d, e)
Agora JACK_QUEEN_OTHER(USER)
se tornaEXPANSION2(ReSeRvEd_JACK, 1, 2, 3)
Isso dá a oportunidade de adicionar várias vírgulas de acordo com a correspondência de uma string:
#define ReSeRvEd_JACK x,x,x
#define ReSeRvEd_QUEEN x,x
Se USER é JACK, JACK_QUEEN_OTHER(USER)
torna-seEXPANSION2(x,x,x, 1, 2, 3)
Se USER é QUEEN, JACK_QUEEN_OTHER(USER)
torna-seEXPANSION2(x,x, 1, 2, 3)
Se USER for outro, JACK_QUEEN_OTHER(USER)
torna-seEXPANSION2(ReSeRvEd_other, 1, 2, 3)
Nesse ponto, algo crítico aconteceu: o quarto argumento para a macro EXPANSION2 é 1, 2 ou 3, dependendo se o argumento original aprovado foi valete, rainha ou qualquer outra coisa. Portanto, tudo o que temos a fazer é escolher. Por razões prolixas, precisaremos de duas macros para a última etapa; eles serão EXPANSION2 e EXPANSION3, embora um pareça desnecessário.
Juntando tudo, temos estas 6 macros:
#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
E você pode usá-los assim:
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
}
Link Godbolt obrigatório: https://godbolt.org/z/8WGa19