2010-10-05 24 views
6

Al usar va_start(), va_arg() y va_end() para leer los parámetros pasados ​​a un método, ¿hay una manera de contar cuántos argumentos hay?Contar el número de parámetros en el método de argumento de la variable C llamada

De acuerdo con la página de manual si se llama va_arg() demasiadas veces se obtiene "errores aleatorios":

Si no hay siguiente argumento, o si tipo no es compatible con el tipo de el siguiente argumento real (como promocionado de acuerdo con las promociones de argumento predeterminadas ), se producirán errores aleatorios.

+0

http://groups.google.com/group/comp.std.c/browse_frm/ thread/77ee8c8f92e4a3fb – Nyan

Respuesta

11

No. una función de Argumento Variable (como printf), debe "saber" cuándo dejar de buscar más argumentos.

printf sabe por el número de %d, %s y otros símbolos en su cadena de formato.

Otras funciones a veces utilizar valores Sentinel:

sumValues(1, 3, 5, 7, 6, 9, -1); // will add numbers until it encounters a -1 

Otras funciones pueden tener el número de parámetros establecidos por adelantado:

AddNames(4, "Bill", "Alice", "Mike", "Tom"); 
5

Hay dos maneras de saber cómo se pasaron muchos argumentos. En primer lugar, puede hacer que uno de los parámetros de función lo indique (como printf, por ejemplo). La otra forma es tener un valor centinela al final de su lista, por ejemplo, puede detenerse en un argumento NULL.

Puede usar va_copy si elige el segundo método, pero aún desea contar los parámetros antes de decidir qué hacer con ellos.

8

Aquí es un truco bastante sorprendente que le permite construir lo que desee mediante macros variadic de C99:

PP_NARG()
Devuelve el número de argumentos contenidos en __VA_ARGS__

Puede utilizar esta para escribir una macro envolviendo su función real que agrega un conteo al frente de los argumentos de la función real.

Véase también this question. Sin embargo, probablemente los enfoques clásicos sean todavía más sensatos durante un año o tres.


El código, por lo que esta respuesta es útil incluso sin el archivo Usenet ...

/* The PP_NARG macro returns the number of arguments that have been 
    * passed to it. 
    */ 

#define PP_NARG(...) \ 
     PP_NARG_(__VA_ARGS__,PP_RSEQ_N()) 
#define PP_NARG_(...) \ 
     PP_ARG_N(__VA_ARGS__) 
#define PP_ARG_N(\ 
      _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ 
     _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ 
     _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ 
     _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ 
     _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ 
     _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ 
     _61,_62,_63,N,...) N 
#define PP_RSEQ_N() \ 
     63,62,61,60,     \ 
     59,58,57,56,55,54,53,52,51,50, \ 
     49,48,47,46,45,44,43,42,41,40, \ 
     39,38,37,36,35,34,33,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 
+0

Debo decir que esto es encantador :-) Nice finding! – jweyrich

+0

¡Exactamente lo que voy a decir! – Nyan

+0

P99 tendrá un conjunto de macros inspiradas en eso y que podría ser exactamente lo que necesita. Lamentablemente, el lanzamiento se realizará solo durante la semana, pero si desea consultar la documentación: http://p99.gforge.inria.fr/p99-html/group__variadic.html –

Cuestiones relacionadas