Ответ 1
Ответ предоставлен в комментариях Hans Passant:
Документированный _ vscprintf предоставляет эту функцию в Windows, поэтому полагаться на "неуказанное поведение" не требуется.
В настоящее время я конвертирую код одной из наших библиотек Linux в DLL Windows.
Внутри этой библиотеки у меня есть функция, которая принимает последние параметры в printf-way (строка форматирования, затем многоточие). Внутри этой функции я использую vsnprintf для форматирования прилагаемых аргументов. Поскольку я хочу знать, могу ли я втиснуть финальную строку в небольшой буфер или если мне придется выделять памяти для меня, я заинтересован в определении "длины длины" форматированной строки.
Для этого в настоящее время я использую vsnprintf как это (например, код примера):
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
void foo(const char* fmt, ...)
{
int len = 0;
va_list ap;
va_start(ap, fmt);
len = vsnprintf(0, 0, fmt, ap);
printf("len = %d\n", len);
va_end(ap);
}
int main(void)
{
foo("12345%s", "67890");
exit(0);
}
Это использование покрывается Open Base Base Specifications Issue 6:
vsnprintf (char * ограничивать s, size_t n, const char * ограничивать формат, va_list ap)
Функции [...] vsnprintf() [...] должны быть эквивалентны [...] snprintf().
snprintf (char * ограничивать s, size_t n, const char * ограничивать формат,...)
Если значение n равно нулю при вызове snprintf(), ничего не должно быть записано, число байтов, которое было бы написано, было бы достаточно большим, исключая завершающий нуль, и оно может быть нулевой указатель.
Проблема возникла, когда я компилировал этот код в Windows-System (Visual Studio 2010) с помощью /analysis on. Компилятор/анализатор дал мне следующее:
test.c(11): предупреждение C6309: аргумент '1' имеет значение null: это не соответствует спецификации функции 'vsnprintf'
test.c(11): предупреждение C6387: "аргумент 1" может быть "0": это не соответствует спецификации функции "vsnprintf": Линии: 7, 8, 10, 11
Быстрый просмотр записи MSDN для vsnprintf дал мне следующее:
Если буфер или формат NULL, или если количество меньше или равно нулю, эти функции вызывают недопустимый обработчик параметров, как описано в разделе Проверка параметров. Если выполнение разрешено продолжить, эти функции возвращают -1.
Любопытно, что вышеприведенный образец работает, тем не менее, в Windows "как и ожидалось" (т.е. возвращает мне счет символов, которые будут записаны).
Но так как я не хочу, чтобы это полагалось на что-то неуказанное, я хотел бы знать, есть ли лучший, официальный способ добиться того же самого, не надеясь, что это не сломается в какой-то будущей версии.
Спасибо за ваше время!
Ответ предоставлен в комментариях Hans Passant:
Документированный _ vscprintf предоставляет эту функцию в Windows, поэтому полагаться на "неуказанное поведение" не требуется.
Возьмите этот пример из справочной страницы snprintf:
Вот как распределить буфер, чтобы соответствовать вашей строке.
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
char *
make_message(const char *fmt, ...)
{
int n;
int size = 100; /* Guess we need no more than 100 bytes. */
char *p, *np;
va_list ap;
if ((p = malloc(size)) == NULL)
return NULL;
while (1) {
/* Try to print in the allocated space. */
va_start(ap, fmt);
n = vsnprintf(p, size, fmt, ap);
va_end(ap);
/* If that worked, return the string. */
if (n > -1 && n < size)
return p;
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n+1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */
if ((np = realloc (p, size)) == NULL) {
free(p);
return NULL;
} else {
p = np;
}
}
}