Я хотел бы создать функцию, которая принимает переменное количество аргументов, причем один из этих аргументов сам является va_list
; но что-то не получается в моем коде, и я не понимаю, что ...Поместите переменную va_list внутри ... список переменных аргументов (!)
ПРЕДУПРЕЖДЕНИЕ. Мой вопрос заключается не в разработке кода, выполняющего то, что я хочу сделать (я нашел способ обойти проблему), но только о понимании того, что я сделал неправильно ...
Чтобы объяснить мой вопрос, давайте начнем с простого примера, а именно: функция ffprintf
, которая действует как fprintf
, но писать его содержимое на несколько строк, строк, число которых указанный первым аргументом ffprintf
, и тождества которого задаются самыми следующими аргументами (число этих аргументов может варьироваться от одного вызова к другому, поэтому вам нужно использовать переменную argum ent список). Такая функция будет использоваться следующим образом:
FILE *stream0, *stream1, *stream2;
int a, b;
ffprintf (3, stream0, stream1, stream2, "%d divided by %d worths %f", a, b, (double)a/b);
И его код будет:
void ffprintf (int z, ...)
{va_list vlist, auxvlist;
FILE **streams = malloc (z * sizeof(FILE *));
va_start (vlist, z);
for (int i = 0; i < z; ++i)
{streams[i] = va_arg (vlist, FILE *); // Getting the next stream argument
}
char const *format = va_arg (vlist, char const *); // Getting the format argument
for (int i = 0; i < z; ++i)
{va_copy (auxvlist, vlist); // You have to work on a copy "auxvlist" of "vlist", for otherwise "vlist" would be altered by the next line
vfprintf (streams[i], format, auxvlist);
va_end (auxvlist);
}
va_end (vlist);
free (streams);
}
Это работает отлично. Теперь, есть также стандартная функция vfprintf
, прототипом которого является vfprintf (FILE *stream, char const* format, va_list vlist);
, и который вы используете, как это, чтобы создать другую функцию, имеющую переменный список аргументов:
void fprintf_variant (FILE *stream, char const* format, ...)
{
va_list vlist;
va_start (vlist, format);
vfprintf (stream, format, vlist);
va_end (vlist);
}
Это работает тоже хорошо. Теперь моя цель состоит в том, чтобы объединить обе идеи, чтобы создать функцию, которую я бы назвал vffprintf
, который вы будете использовать, как это:
FILE *stream0, *stream1, *stream2;
void fprintf_onto_streams012 (char const *format, ...)
{va_list vlist;
va_start (vlist, format);
vffprintf (3, stream0, stream1, stream2, format, vlist);
va_end (vlist);
}
Я разработал следующий код:
void vffprintf (int z, ...)
{va_list vlist, auxvlist, auxauxvlist;
va_start (vlist, z);
FILE **streams = malloc (z * sizeof(FILE *));
for (int i = 0; i < z; ++i)
{streams[i] = va_arg (vlist, FILE *);
}
char const *format = va_arg (vlist, char const *);
va_copy (auxvlist, va_arg (vlist, va_list)); // Here I get the next argument of "vlist", knowing that this argument is of "va_list" type
for (int i = 0; i < z; ++i)
{va_copy (auxauxvlist, auxvlist);
vfprintf (streams[i], format, auxvlist);
va_end (auxauxvlist);
}
va_end (auxvlist);
va_end (vlist);
free (streams);
}
Этот код компилируется без сучка, но он не работает должным образом ... например, если я пишу следующий код: полный
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
void vffprintf (int z, ...)
{va_list vlist, auxvlist, auxauxvlist;
FILE **streams = malloc (z * sizeof(FILE *));
va_start (vlist, z);
for (int i = 0; i < z; ++i)
{streams[i] = va_arg (vlist, FILE *);
}
char const *format = va_arg (vlist, char const *);
va_copy (auxvlist, va_arg (vlist, va_list));
for (int i = 0; i < z; ++i)
{va_copy (auxauxvlist, auxvlist);
vfprintf (streams[i], format, auxauxvlist);
va_end (auxauxvlist);
}
va_end (auxvlist);
va_end (vlist);
free (streams);
}
void printf_variant (char const *format, ...)
{va_list vlist;
va_start (vlist, format);
vffprintf (1, stdout, format, vlist);
va_end (vlist);
}
int main (void)
{printf_variant ("Ramanujan's number is %d.\n", 1729);
return 0;
}
Я получаю Segfault ... Почему ?!!
P.-S .: Извините за этот очень длинный вопрос; но я хотел, чтобы это было совершенно ясно, потому что это довольно технически ...
P.-S.2: Я использовал намеренно оба тега «va-list» и «alternargumentlists» для этого вопроса, потому что меня интересует is va_list
, рассматривается как тип, внутри (другой) список переменных аргументов, рассматривается как список ... Так что это действительно две разные концепции.
Итак, вопрос в том, почему последний пример не работает? – this
Да, это именно то, что :-) –
Выглядит хорошо, если вы игнорируете утечку памяти. – this