Il existe un problème bien connu avec les arguments vides pour les macros variadiques dans C99.
exemple:
#define FOO(...) printf(__VA_ARGS__)
#define BAR(fmt, ...) printf(fmt, __VA_ARGS__)
FOO("this works fine");
BAR("this breaks!");
L'utilisation de BAR()
ci-dessus est en effet incorrecte selon la norme C99, car elle s'étendra à:
printf("this breaks!",);
Notez la virgule de fin - pas réalisable.
Certains compilateurs (par exemple: Visual Studio 2010) se débarrasseront discrètement de cette virgule de fin pour vous. D'autres compilateurs (par exemple: GCC) prennent en charge la mise ##
devant __VA_ARGS__
, comme ceci:
#define BAR(fmt, ...) printf(fmt, ##__VA_ARGS__)
Mais existe-t-il un moyen conforme aux normes d'obtenir ce comportement? Peut-être utiliser plusieurs macros?
À l'heure actuelle, la ##
version semble assez bien prise en charge (du moins sur mes plateformes), mais je préfère vraiment utiliser une solution conforme aux normes.
Préemptif: je sais que je pourrais simplement écrire une petite fonction. J'essaye de faire ceci en utilisant des macros.
Edit : Voici un exemple (bien que simple) de la raison pour laquelle je voudrais utiliser BAR ():
#define BAR(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
BAR("here is a log message");
BAR("here is a log message with a param: %d", 42);
Cela ajoute automatiquement une nouvelle ligne à mes instructions de journalisation BAR (), en supposant qu'il fmt
s'agit toujours d'une chaîne C entre guillemets. Il n'imprime PAS la nouvelle ligne en tant que printf () distincte, ce qui est avantageux si la journalisation est mise en tampon en ligne et provient de plusieurs sources de manière asynchrone.
__VA_OPT__
mot - clé. Cela a déjà été "adopté" par C ++, donc je pense que C suivra. (je ne sais pas si cela signifie qu'il a été accéléré dans C ++ 17 ou s'il est défini pour C ++ 20)
BAR
au lieu deFOO
en premier lieu?