Vous ne pouvez pas faire cela si USER est défini comme une chaîne entre guillemets.
Mais vous pouvez le faire si USER est juste JACK, QUEEN ou Joker ou autre.
Il y a deux astuces à utiliser:
- Token-splicing, où vous combinez un identifiant avec un autre identifiant en concaténant simplement leurs caractères. Cela vous permet de comparer avec JACK sans avoir à
#define JACK
faire quelque chose
- expansion de macro variadic, qui vous permet de gérer des macros avec un nombre variable d'arguments. Cela vous permet d'étendre des identifiants spécifiques en un nombre variable de virgules, qui deviendront votre comparaison de chaînes.
Alors commençons par:
#define JACK_QUEEN_OTHER(u) EXPANSION1(ReSeRvEd_, u, 1, 2, 3)
Maintenant, si j'écris JACK_QUEEN_OTHER(USER)
et que USER est JACK, le préprocesseur le transforme enEXPANSION1(ReSeRvEd_, JACK, 1, 2, 3)
La deuxième étape est la concaténation:
#define EXPANSION1(a, b, c, d, e) EXPANSION2(a##b, c, d, e)
maintenant , JACK_QUEEN_OTHER(USER)
devientEXPANSION2(ReSeRvEd_JACK, 1, 2, 3)
Cela donne la possibilité d'ajouter un certain nombre de virgules selon qu'une chaîne correspond ou non:
#define ReSeRvEd_JACK x,x,x
#define ReSeRvEd_QUEEN x,x
Si USER est JACK, JACK_QUEEN_OTHER(USER)
devientEXPANSION2(x,x,x, 1, 2, 3)
Si USER est REINE, JACK_QUEEN_OTHER(USER)
devientEXPANSION2(x,x, 1, 2, 3)
Si USER est autre, JACK_QUEEN_OTHER(USER)
devientEXPANSION2(ReSeRvEd_other, 1, 2, 3)
À ce stade, quelque chose de critique s'est produit: le quatrième argument de la macro EXPANSION2 est 1, 2 ou 3, selon que l'argument d'origine passé était jack, queen ou autre. Tout ce que nous avons à faire est donc de le sélectionner. Pour de longues raisons, nous aurons besoin de deux macros pour la dernière étape; ce seront EXPANSION2 et EXPANSION3, même si l'une semble inutile.
En mettant tout cela ensemble, nous avons ces 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
Et vous pourriez les utiliser comme ceci:
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
}
Lien godbolt obligatoire: https://godbolt.org/z/8WGa19