Почему vsnprintf не записывает такое же количество символов, как strncpy?
Я задал тот же вопрос о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 ответа
Кто-нибудь может объяснить несоответствие?
Потому что их документированное поведение отличается.
strncpy()
Если число достигнуто до того, как весь массив src был скопирован, результирующий массив символов не заканчивается нулем.
но vsnprintf()
Максимум buf_size-1 символов написано. Результирующая символьная строка будет оканчиваться нулевым символом, если только buf_size не равен нулю.
Акцент мой.
Потому что страница руководства ясно говорит, что
Если выходные данные были усечены из-за этого ограничения, тогда возвращаемое значение - это количество символов (не включая завершающий символ '\0'), которые были бы записаны в последнюю строку, если бы было достаточно места.
Если вы проверите возвращаемое значение вашего второго vsnprintf
call, вы увидите, что возвращаемое значение равно размеру, как на странице man:
Таким образом, возвращаемое значение размера или более означает, что вывод был усечен.
buf_size
параметр для vsnprintf
указывает, сколько символов нужно написать, включая завершающий символ NUL. Возвращаемое значение - количество произведенных символов, не включая завершающий символ NUL.
Ты хочешь
const auto buf_size = vsnprintf(nullptr, 0U, format, vlist) + 1;