Подтвердить что ты не робот

Unix для Windows: альтернатива vsnprintf для определения длины?

В настоящее время я конвертирую код одной из наших библиотек 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 "как и ожидалось" (т.е. возвращает мне счет символов, которые будут записаны).

Но так как я не хочу, чтобы это полагалось на что-то неуказанное, я хотел бы знать, есть ли лучший, официальный способ добиться того же самого, не надеясь, что это не сломается в какой-то будущей версии.

Спасибо за ваше время!

4b9b3361

Ответ 1

Ответ предоставлен в комментариях Hans Passant:

Документированный _ vscprintf предоставляет эту функцию в Windows, поэтому полагаться на "неуказанное поведение" не требуется.

Ответ 2

Возьмите этот пример из справочной страницы 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;
        }
    }
}