Esta es una pregunta extraña, pero ¿existe una forma estándar de manipular el contenido de un va_list
antes de pasarlo a otra función? Por ejemplo, supongamos que tengo dos funciones, sum
y vsum
:¿Manera estándar de manipular argumentos variados?
int vsum(int n, va_list ap) {
int total = 0;
for (int i = 0; i < n; ++i) {
total += va_arg(n, int);
return total;
}
int sum(int n, ...) {
va_list ap;
va_start(ap, n);
int total = vsum(n, ap);
va_end(ap);
return total;
}
Si llamo sum
como sum(4, 1, 2, 3, 4)
, espero que para obtener el resultado 10. Ahora supongamos que en lugar de llamar vsum
directamente, sum
llama a una función intermedia , vsum_stub
el que hace lo siguiente:
int vsum_stub(int n, va_list ap) {
va_list temp_ap;
va_copy(temp_ap, ap);
for (int i = 0; i < n; ++i) {
int *arg = &va_arg(ap, int);
*arg += 2;
}
va_end(temp_ap);
return vsum(n, ap);
}
Ahora cuando llamo sum(4, 1, 2, 3, 4)
, debería volver el número 20, ya que todos los vsum_stub
incrementos de los valores de la va_list
por 2. Esto no compila, por supuesto, ya que no puede tomar la dirección del resultado de va_arg
. ¿Hay otra forma de hacer esto? Estoy trabajando en C99.
Antecedentes:
Estoy trabajando en una biblioteca que hace alguna traducción puntero de modo que los datos pueden ser almacenados en el montón en un formato más eficiente. Los programas se compilan con una transformación personalizada que convierte las llamadas a funciones de biblioteca como printf
en mis propias funciones de código auxiliar (por ejemplo, hc_printf
). hc_printf
necesita traducir cualquier argumento de puntero (cadenas destinadas a %s
) antes de pasar los argumentos a la función real printf
.
Editar: Aquí hay un ejemplo de código. Digamos que tenemos una cadena foo
. foo
se asigna dinámicamente con una versión modificada de malloc
que devuelve un puntero falso. El compilador modifica el programa para que pueda manejar punteros falsos. Por lo que este funciona:
char *foo = fake_malloc(4);
fake_strcpy(foo, "foo");
Quiero escribir una función fake_vprintf
como esto (en pseudocódigo):
int fake_vprintf(const char *format, va_list args) {
for each pointer argument p in args
translate p to q, a real pointer to contiguous memory
replace p with q in args
}
return vprintf(format, args);
}
El programa llamaría fake_vprintf
igual que el original vprintf
usando el puntero falso. fake_vprintf
traduce el puntero falso a un puntero real que puede usar el real vprintf
.
No debería 'int * arg = & va_arg (ap, int);' en realidad ser 'int * arg = va_arg (ap, int *);'? – dirkgently
@dirkgently, no, el parámetro real dentro de la lista de argumentos es un int. Mi intención en ese ejemplo era obtener un puntero a ese int dentro de la lista para poder cambiar su valor. –
Supuse que el 'vsum_stub' toma una lista de' int * '. De todos modos, ¿cree que el código que publiqué es de alguna ayuda? – dirkgently