Я пишу функцию в C, которая принимает переменное число аргументов.
size_t myprintf(char *fmt, ...);
Пока все хорошо. Я решил, что лучше сделать все правильно и сделать версию, которая принимает переменные аргументы, и другую версию, которая принимает va_list
.
size_t myprintf(char *fmt, ...);
size_t myvprintf(char *fmt, va_list args);
Не так сложно это сделать. За исключением того, что my_vprintf()
необходимо отправить args
двум различным функциям (сначала на snprintf()
длиной 0, чтобы определить, сколько места нам нужно, затем на sprintf()
после того, как мы выделим столько места). Я делаю это с va_copy
.
size_t myvprintf(char *fmt, va_list args)
{
va_list args2;
va_copy(args, args2);
// do stuff with args2
va_end(args2);
// do more stuff with args
}
Это все прекрасно и круто, но C99 немного плохо реализован. Я хотел бы, если возможно, чтобы мой код работал и в C89, и для работы с как можно большим количеством компиляторов и на как можно большем количестве платформ. В настоящее время у меня есть это после #include <stddef.h>
, но перед любым кодом:
#ifndef va_copy
# ifdef __va_copy
# define va_copy(a,b) __va_copy(a,b)
# else /* !__va_copy */
# define va_copy(a,b) ((a)=(b))
# endif /* __va_copy */
#endif /* va_copy */
Меня убеждают, что ((a)=(b))
ненадежен, и что мне, возможно, следует использовать memcpy()
или что-то подобное, но это все еще на уровне «Если вы не поддерживаете C99, я надеюсь, что это работает» а не «Если вы не поддерживаете C99, никогда не бойтесь» (именно этого я и хочу). Есть ли хороший способ обойти это ограничение? Я видел несколько решений - va_list
функций, которые используют один аргумент и рекурсивно, передавая va_list
дважды для создания двух отдельных копий и т. Д. - но я не знаю, насколько хорошо они будут работать (и Рекурсивное решение не будет так хорошо, если я просто хочу позвонить vsnprintf()
, не так ли?).
Итак, я обращаюсь к вам, пользователь StackOverflow. Могу ли я сделать что-нибудь еще, чтобы обеспечить совместимость с C89, или пользователям без va_copy
и __va_copy
(по общему признанию, мало и далеко) просто придется смириться с этим и взять его?