0
votes

C macro qui détecte l'argument vide puis utilise le cas par défaut

J'ai des macros qui vont soit élargir dans un nombre (dans mon exemple, les cas 2 et 4), ou rien (dans mon exemple, les cas 1 et 3). Le néant n'est pas souhaitable pour moi, j'ai donc besoin d'autres macros qui détecteront et remplacent le néant.

J'ai pu créer une macro, old_check code>, qui détecterait le cas et remplacerait avec un 0. (cas 1) p>

Je veux l'améliorer et créer une nouvelle macro, new_check code>, qui détectera le cas et le remplacera par une valeur par défaut. valeur. (Cas 3) P>

#define NEW_CHECK_HELPER(...) , ## __VA_ARGS__
#define NEW_CHECK(default, ...) (default NEW_CHECK_HELPER(__VA_ARGS__))


1 commentaires

Mettre la macro dans la question.


4 Réponses :


0
votes

Votre méthode existante fonctionnera si vous vous débarrassez de la virgule de fuite dans le cas triple: xxx

La raison est que GCC fait une distinction entre aucun argument et un argument vide pour , ## __ va_args __ - seulement s'il y a aucun argument ne supprime-t-il la virgule (unique) vide le garde.

alors il y a l'étrangeté que old_check () est traité comme aucun argument plutôt qu'un argument vide , ce qui n'a pas encore beaucoup de sens.


0 commentaires

0
votes

Si vous avez vraiment besoin de prendre en charge l'argument "vide" dans le cas 3, vous pouvez essayer le non-portable:

case 3: 7
case 4: 5


2 commentaires

Merci; Mon problème a besoin de gérer la virgule suivante. Malheureusement, la non-portabilité de la solution est une question. Mon environnement ne prend pas en charge __ va_opt __ , que j'ai testé avec mon enfant à la fois mon enfant et avec Ce .


Assez juste; J'ai ajouté une deuxième réponse qui utilise le de GCC, ## __ va_args __ syntaxe.



0
votes

Utilisation de de GCC, ## __va_args __ Extension pour la suppression des virgules (que vous utilisez déjà pour OLD_CHECK ): xxx

impressions : xxx


0 commentaires

0
votes

Après un moment, j'ai proposé une solution de plusieurs étapes alternative tout aussi portable que old_check code>. Il réutilise premier_one code> d'avant, et utilise également une macro nargs nargs code> pour compter le nombre d'arguments dans __ va_args __ code>.

/* NEW_CHECK(default, maybe_blank) */
#define NEW_CHECK(...) M_(__VA_ARGS__)
/* delay expansion of M once to perform Q */
#define M_(D, ...) F(D, Q(__VA_ARGS__))
/* Q(maybe_blank): if __VA_ARGS__ is non-blank, __VA_ARGS__. Otherwise, SPACE */
#define Q(...) FIRST_ONE(dummy, ##__VA_ARGS__, SPACE)
/* SPACE just expands into two arguments so that we can differentiate between was-blank (2 args) and non-blank (1 arg) */
#define SPACE 0, 0
/* F(default, one-or-two-arguments) */
#define F(...) F_(__VA_ARGS__)
#define F_(...) F__(__VA_ARGS__)
/* delay expansion of F twice, for performing Q and SPACE */
#define F__(D, ...) H(NARGS(__VA_ARGS__), D, __VA_ARGS__)
/* H(1 or 2, default, maybe_blank) */
#define H(...) H_(__VA_ARGS__)
/* delay expansion once, for performing NARGS */
#define H_(N, D, ...) DO##N(D, __VA_ARGS__)
/* based on NARGS, pick correct result */
#define DO1(D, ...) __VA_ARGS__
#define DO2(D, ...) D


0 commentaires