Почему vsnprintf не записывает такое же количество символов, как strncpy? - PullRequest
0 голосов
/ 10 января 2019

Я задавал тот же вопрос о strncpy, но там string заканчивается всей входной строкой. При передаче строки в vsnprintf последний символ всегда обрезается: https://rextester.com/UIQMX91570

Для простоты я также включил ссылку на пример в реальном времени в коде:

void bar(const char* format, va_list vlist) {
    const auto buf_size = vsnprintf(nullptr, 0U, format, vlist);
    string buffer(buf_size, '\0');

    vsnprintf(data(buffer), buf_size, format, vlist);
    cout << data(buffer) << endl;
}

void foo(const char* format, ...) {
    va_list vlist;

    va_start(vlist, format);
    bar(format, vlist);
    va_end(vlist);
}

Если я вызову это с: foo("lorem ipsum %d", 13), то получу вывод:

lorem ipsum 1

Где, как я и ожидал: lorem ipsum 13

Может кто-нибудь объяснить несоответствие? При отладке я получаю buf_size из 14, что должно быть достаточным, чтобы содержать всю строку, но этого не происходит: (

Ответы [ 3 ]

0 голосов
/ 10 января 2019

Параметр buf_size для vsnprintf указывает количество символов для записи, , включая завершающий символ NUL . Возвращаемое значение - количество произведенных символов, без учета завершающего символа NUL .

Вы хотите

const auto buf_size = vsnprintf(nullptr, 0U, format, vlist) + 1;
0 голосов
/ 10 января 2019

Кто-нибудь может объяснить несоответствие?

Потому что их документированное поведение отличается.

strncpy()

Если число достигнуто до того, как был скопирован весь массив src, результирующий массив символов не заканчивается нулем .

но vsnprintf()

Максимум buf_size-1 символов написано. Результирующая строка символов будет оканчиваться нулевым символом, если только buf_size не равен нулю.

Акцент мой.

0 голосов
/ 10 января 2019

Потому что страница руководства ясно говорит, что

Если выходные данные были усечены из-за этого ограничения, тогда возвращаемое значение - это количество символов (не включая завершающий '\ 0'), которое было бы записано в последнюю строку, если бы было достаточно места.

Если вы проверите возвращаемое значение вашего второго vsnprintf вызова, вы увидите, что возвращаемое значение равно размеру, как на странице man:

Таким образом, возвращаемое значение размера или более означает, что результат был усеченный.

...