Reenviar una invocación de una función variada en C

Resuelto Patrick asked hace 16 años • 13 respuestas

En C, ¿es posible reenviar la invocación de una función variada? Como en,

int my_printf(char *fmt, ...) {
    fprintf(stderr, "Calling printf with fmt %s", fmt);
    return SOMEHOW_INVOKE_LIBC_PRINTF;
}

Obviamente, reenviar la invocación de la manera anterior no es estrictamente necesario en este caso (ya que puede registrar las invocaciones de otras maneras o usar vfprintf), pero el código base en el que estoy trabajando requiere que el contenedor haga un trabajo real, y no No tiene (y no puede haber agregado) una función auxiliar similar a vfprintf.

[Actualización: parece haber cierta confusión según las respuestas proporcionadas hasta ahora. Para expresar la pregunta de otra manera: en general, ¿se puede ajustar alguna función variable arbitraria sin modificar la definición de esa función ?]

Patrick avatar Sep 30 '08 03:09 Patrick
Aceptado

Si no existe una función análoga a vfprintfla que tome un va_listnúmero variable de argumentos en lugar de un número variable, no hay manera .

Ejemplo:

void myfun(const char *fmt, va_list argp) {
    vfprintf(stderr, fmt, argp);
}
Adam Rosenfield avatar Sep 29 '2008 20:09 Adam Rosenfield

No directamente, sin embargo, es común (y encontrará este caso casi universalmente en la biblioteca estándar) que las funciones variadas vengan en pares con una varargsfunción alternativa de estilo. p.ej printf/vprintf

Las funciones v... toman un parámetro va_list, cuya implementación a menudo se realiza con 'macro magic' específica del compilador, pero se garantiza que llamar a la función de estilo v... desde una función variada como esta funcionará:

#include <stdarg.h>

int m_printf(char *fmt, ...)
{
    int ret;

    /* Declare a va_list type variable */
    va_list myargs;

    /* Initialise the va_list variable with the ... after fmt */

    va_start(myargs, fmt);

    /* Forward the '...' to vprintf */
    ret = vprintf(fmt, myargs);

    /* Clean up the va_list */
    va_end(myargs);

    return ret;
}

Esto debería darte el efecto que estás buscando.

Si está considerando escribir una función de biblioteca variada, también debería considerar hacer que un complemento de estilo va_list esté disponible como parte de la biblioteca. Como puede ver en su pregunta, puede resultar útil para sus usuarios.

CB Bailey avatar Sep 29 '2008 20:09 CB Bailey