Опираясь на Sylvain * answer , здесь есть простая реализация с asprintf()
и vasprintf()
, потому что там, где вам нужен один, вам обычно тоже нужен другой,И, учитывая макрос va_copy()
из C99, легко реализовать asprintf()
в терминах vasprintf()
.Действительно, при написании функций varargs очень часто полезно иметь их в парах, один с многоточием и один с аргументом va_list
вместо многоточия, и вы тривиально реализуете первый в терминах последнего.
Это приводит к коду:
int vasprintf(char **ret, const char *format, va_list args)
{
va_list copy;
va_copy(copy, args);
/* Make sure it is determinate, despite manuals indicating otherwise */
*ret = NULL;
int count = vsnprintf(NULL, 0, format, args);
if (count >= 0)
{
char *buffer = malloc(count + 1);
if (buffer == NULL)
count = -1;
else if ((count = vsnprintf(buffer, count + 1, format, copy)) < 0)
free(buffer);
else
*ret = buffer;
}
va_end(copy); // Each va_start() or va_copy() needs a va_end()
return count;
}
int asprintf(char **ret, const char *format, ...)
{
va_list args;
va_start(args, format);
int count = vasprintf(ret, format, args);
va_end(args);
return(count);
}
Сложной частью использования этих функций в системе, где они не предусмотрены, является решение, где функции должны быть объявлены.В идеале они были бы в <stdio.h>
, но тогда вам не нужно было бы их писать.Итак, у вас должен быть какой-то другой заголовок, который включает <stdio.h>
, но объявляет эти функции, если они не объявлены в <stdio.h>
.И, в идеале, код должен полуавтоматически обнаруживать это.Может быть, заголовок "missing.h"
и содержит (частично):
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
#include <stdarg.h>
#ifndef HAVE_ASPRINTF
extern int asprintf(char **ret, const char *format, ...);
extern int vasprintf(char **ret, const char *format, va_list args);
#endif /* HAVE_ASPRINTF */
Также обратите внимание, что эта справочная страница для asprintf () говорит, что возвращаемое значение в указателенеопределенный в случае ошибки.Другие справочные страницы , включая ту, на которую есть ссылка в вопросе, указывают, что в случае ошибки для нее явно установлено значение NULL.В документе комитета по стандарту C ( n1337.pdf ) не указано поведение ошибки при нехватке памяти.
- При использовании asprintf () не предполагайте, что указатель инициализированесли функция завершается ошибкой.
- Если реализуется asprintf (), убедитесь, что для указателя установлено значение null при ошибке, чтобы дать детерминированное поведение.