Pasar puntos suspensivos a otra función variádica [duplicate]

4 minutos de lectura

avatar de usuario
mensaje de tim

Tengo aproximadamente 30 funciones variádicas. Cada uno acepta una ruta como argumento final, por ejemplo:

bool do_foo(struct *f, int q, const char *fmt, ...)

En cada función, tengo que verificar que el formato expandido sea menor o igual a un tamaño determinado. Entonces, me encuentro copiando / pegando el mismo fragmento de código para verificar cuántos caracteres vsnprintf() no imprimió, estableció errno en consecuencia y salir de la escritura.

Lo que me gustaría hacer es escribir una función para hacer esto, que devolvería una cadena asignada estáticamente (expandida) que se sabe que tiene un tamaño seguro, o una cadena recién inicializada en caso de falla, que podría verificarse con NULL. Las comprobaciones también deben determinar si la cadena es una ruta absoluta o relativa, lo que influye en el tamaño seguro de la cadena. Es un montón de código duplicado y está empezando a oler mal.

¿Hay alguna forma de pasar el contenido de los puntos suspensivos de la entrada de mi función a otra función? O tengo que llamar va_start() primero, y luego pasar el va_list a la función auxiliar?

Editar:

No me opongo en absoluto a aprobar el va_list al ayudante, solo quería asegurarme de que no existiera nada más. Me parece que el compilador entiende dónde comienzan los argumentos variados, así que tenía curiosidad por saber si podía decirle que los pasara.

  • ¿Hay algún motivo por el que se resista a pasar la va_list al ayudante?

    – ojblass

    30 de marzo de 2009 a las 4:17

  • Tuve que hacer cosas de tipo similar, pero tuve que eliminar algunos de los argumentos… no era un código agradable de mantener.

    – ojblass

    30 de marzo de 2009 a las 4:18

No puede, solo puede pasar los argumentos como un va_list. Ver el Preguntas frecuentes sobre comp.lang.c.

En general, si está escribiendo funciones variádicas (es decir, funciones que toman un número variable de argumentos) en C, debe escribir dos versiones de cada función: una que tome puntos suspensivos (...), y uno que toma un va_list. La versión que toma puntos suspensivos debería llamar va_startllamar a la versión tomando un va_listllamada va_end, y volver. No hay necesidad de duplicación de código entre las dos versiones de la función, ya que una llama a la otra.

  • Sería bueno si escribieras el código.

    –Andrew Rasmussen

    19 de agosto de 2014 a las 0:49

  • ¿Qué debo hacer si necesito hacer cosas con va_list ¿dos veces? Normalmente, tendría que llamar va_end y va_start entre usos (de lo contrario, es UB), pero no puedo llamarlo en una función que toma va_list: ‘va_start’ used in function with fixed args.

    – rr-

    19/09/2015 a las 15:25

  • No importa, lo descubrí, necesito usar va_copy para cada uso posterior.

    – rr-

    19/09/2015 a las 15:37

  • ¿código? ¡aquí hay un lugar para ayudar a otros también!

    – Vasilis

    5 de noviembre de 2018 a las 16:14

avatar de usuario
qrdl

Probablemente puedas usar macros variadas, como esta:

#define FOO(...)  do { do_some_checks; myfun(__VA_ARGS__); } while (0)

¡NÓTESE BIEN! Las macros variádicas son solo para C99

  • Estaba mirando esos, eso me ahorra tener que agregar un contenedor alrededor de la función que realmente escribe.

    – Tim Publicar

    30 de marzo de 2009 a las 6:28

  • c99 no es un problema, mi programa es más bien específico de gcc/linux

    – Tim Publicar

    30 de marzo de 2009 a las 6:29

No sé si esto ayudará, puede acceder a las variables por referencia. Este es un truco engañoso, pero desafortunadamente no le permitirá usar puntos suspensivos en la definición final de la función.

#include <stdio.h>

void print_vars(int *n)
{
  int i;
  for(i=0;i<=*n;i++)
    printf("%X %d  ", (int)(n+i), *(n+i));
  printf("\n");
}

void pass_vars(int n, ...)
{
  print_vars(&n);
}

int main()
{
    pass_vars(4, 6, 7, 8, 0);
    return 0;
}

En mi pc sale

$ ./a.out
BFFEB0B0 4  BFFEB0B4 6  BFFEB0B8 7  BFFEB0BC 8  BFFEB0C0 0

  • no portatil…

    – Aschepler

    23 de enero de 2013 a las 16:56

Tienes que pasar va_list al ayudante.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad