2010-12-02 11 views
21

Duplicar posible:
C/C++: Passing variable number of arguments around¿Cómo usar __VA_ARGS__ dentro de una función C en lugar de macro?

Actualmente estoy usando la siguiente macro declarado en mi archivo C.

#define COMMON_Print(...) printf (__VA_ARGS__) 

Ahora esa llamada funciona bien, pero resulta que tengo que ser capaz de crear una función de C que se ve algo como esto:

void COMMON_Print(...) 
{  
    printf (__VA_ARGS__); 
} 

Para que la función no funciona, yo obtener un error

"error: no definido __VA_ARGS__ identificador"

La complejidad de mi proyecto requiere tener una función ya que es una interfaz ... Entonces, ¿cómo puedo obtener los parámetros ... y pasarlos a la función printf? O mejor, ¿qué estoy haciendo mal?

Gracias!

+1

ver este http://stackoverflow.com/questions/205529/cc-passing-variable-number-of-arguments -around – Kos

Respuesta

36

Cada una de las funciones ?printf tiene una función correspondiente v?printf que hace lo mismo pero toma un va_list, una lista de argumentos variables.

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

void COMMON_Print(char *format, ...) 
{ 
    va_list args; 

    va_start(args, format); 
    vprintf(format, args); 
    va_end(args); 
} 

Nota al margen: en cuenta que va_start lleva el nombre del último argumento ante el ... como parámetro. va_start es una macro que hace un poco de magia basada en pila para recuperar los argumentos variables y necesita la dirección del último argumento fijo para hacer esto. Como consecuencia de esto, tiene que haber al menos un argumento fijo para que pueda pasarlo a va_start. Es por eso que agregué el argumento format en lugar de seguir con la declaración más simple COMMON_Print(...).

Ver:http://www.cplusplus.com/reference/clibrary/cstdio/vprintf/

+0

Si usa macros, no necesita arg anterior. Considere este ejemplo: '#define LOGI (...) ((void) __ android_log_print (ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS __))' Esto obviamente es muy conveniente desde un punto de vista de uso. –

15

__VA_ARGS__ es sólo para las macros; Las funciones variadas son bastante diferentes. Debe usar va_start, va_arg y va_end desde stdarg.h para manejarlos.

primer lugar, su función necesita al menos un parámetro con nombre, por ejemplo:

void COMMON_Print(const char* fmt, ...) 

A continuación, se puede definir un va_list y utilizar va_start para configurarlo:

va_list args; 
va_start(args, fmt); 
// your code here 
va_end(args); 

Ahora puede utilizar args a acceder a los argumentos; llamando al va_arg(args, TYPE) devolverá el siguiente argumento varónico, por lo que puede seguir llamándolo hasta que haya leído todos los argumentos.

Si sólo está tratando de llamar printf, hay una variante llamada printf vprintf que lleva el va_list directamente:

vprintf(fmt, args); 

No hay manera fácil de llamar a una función variadic de otro; necesita algo como vprintf que toma el total va_list

+0

Gracias por su explicación. ¡Gracias por la ayuda y las explicaciones que realmente ayudaron! :) – Jona

+0

'va_arg (args, TYPE)' devolverá NULL solo si la persona que llama pasó NULL. No hay una condición de finalización predeterminada para va_arg. Debe pasar un valor de centinela o conocer el número exacto de parámetros, pasado por un parámetro o contando el número de% en una cadena de formato printf. –

+0

@tristopia Oh, cierto; Tengo el hábito de pasar NULL al final cuando sea necesario. Corregido –

4

__VA_ARGS__ es solo para macros.

No se puede encadenar el número variable de argumentos a otra función directamente. En su lugar, tiene que pasar una va_list, y la función que está llamando debe tomar una va_list. Por suerte hay una variación de printf que hace esto, su función tiene que ser escrito de esta manera:

void COMMON_Print(char *format,...) 
{  
    va_list args; 
    va_begin(args,format); 
    vsprintf(format,args); 
    va_end(args); 
} 
+1

¡Muchas gracias por su respuesta! ¡Realmente funciona! Pero creo que hay algunos problemas de formato que tengo que resolver. FYI, estoy trabajando en un dispositivo integrado. – Jona

+0

¿Qué es vaprintf? ¿O es solo un error tipográfico? –

Cuestiones relacionadas