121 votes

Préprocesseur C ++ __VA_ARGS__ nombre d'arguments

Question simple pour laquelle je n'ai pas trouvé de réponse sur le net. Dans les macros d’arguments variadiques, comment trouver le nombre d’arguments? Je suis d'accord avec le préprocesseur boost, s'il dispose de la solution.

Si cela fait une différence, j'essaie de convertir un nombre variable d'arguments de macro pour améliorer la séquence, la liste ou le tableau du préprocesseur en vue d'un nouveau traitement.

113voto

qrdl Points 17813

J'ai l'habitude d'utiliser cette macro pour trouver un certain nombre de paramètres:

#define NUMARGS(...)  (sizeof((int[]){__VA_ARGS__})/sizeof(int))

Exemple complet:

#include <stdio.h>
#include <string.h>
#include <stdarg.h>

#define NUMARGS(...)  (sizeof((int[]){__VA_ARGS__})/sizeof(int))
#define SUM(...)  (sum(NUMARGS(__VA_ARGS__), __VA_ARGS__))

void sum(int numargs, ...);

int main(int argc, char *argv[]) {

    SUM(1);
    SUM(1, 2);
    SUM(1, 2, 3);
    SUM(1, 2, 3, 4);

    return 1;
}

void sum(int numargs, ...) {
    int     total = 0;
    va_list ap;

    printf("sum() called with %d params:", numargs);
    va_start(ap, numargs);
    while (numargs--)
        total += va_arg(ap, int);
    va_end(ap);

    printf(" %d\n", total);

    return;
}

Il est tout à fait valable, C99 code. Il a un inconvénient, cependant, vous ne pouvez pas invoquer la macro SUM() sans params, mais GCC a une solution à cela - voir ici.

Ainsi dans le cas de GCC vous avez besoin de définir des macros comme ceci:

#define       NUMARGS(...)  (sizeof((int[]){0, ##__VA_ARGS__})/sizeof(int)-1)
#define       SUM(...)  sum(NUMARGS(__VA_ARGS__), ##__VA_ARGS__)

et il fonctionnera même avec vide de la liste des paramètres

105voto

Kornel Kisielewicz Points 26556

Cela dépend en fait du compilateur et n'est pris en charge par aucun standard.

Ici cependant, vous avez une implémentation de macro qui fait le décompte.

8voto

user1187902 Points 81

Voici comment je l'ai fait https://github.com/aeyakovenko/notes#counting-args-with-c-macros

et fonctionne avec 0 argument. devrait également fonctionner avec les compilateurs Windows.

6voto

user720594 Points 140

Avec l'extension msvc:

 #define Y_TUPLE_SIZE(...) Y_TUPLE_SIZE_II((Y_TUPLE_SIZE_PREFIX_ ## __VA_ARGS__ ## _Y_TUPLE_SIZE_POSTFIX,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))
#define Y_TUPLE_SIZE_II(__args) Y_TUPLE_SIZE_I __args

#define Y_TUPLE_SIZE_PREFIX__Y_TUPLE_SIZE_POSTFIX ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0

#define Y_TUPLE_SIZE_I(__p0,__p1,__p2,__p3,__p4,__p5,__p6,__p7,__p8,__p9,__p10,__p11,__p12,__p13,__p14,__p15,__p16,__p17,__p18,__p19,__p20,__p21,__p22,__p23,__p24,__p25,__p26,__p27,__p28,__p29,__p30,__p31,__n,...) __n
 

Fonctionne pour 0 à 32 arguments. Cette limite peut être facilement étendue.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X