Неоднозначність починається з самого стандарту C. І C99, і C11 мають однаковий опис snprintf
функції. Ось опис від C99:
7.19.6.5 snprintf
Синопсис функції
1 #include <stdio.h>
int snprintf(char * restrict s, size_t n, const char * restrict format, ...);
Опис
2 snprintf
Функція еквівалентна fprintf
, за винятком того, що вихідні дані записуються в масив (зазначений аргументом s
), а не в потік. Якщо n
дорівнює нулю, нічого не записується і s
може бути нульовим покажчиком. В іншому випадку вихідні символи за межами n-1
st відкидаються, а не записуються в масив, а нульовий символ записується в кінці символів, фактично записаних в масив. Якщо копіювання відбувається між об'єктами, що перекриваються, поведінка не визначена.
Повертає
3 snprintf
Функція повертає кількість символів, яку було б записаноn
було достатньо великим, не враховуючи закінчувального нульового символу, або негативного значення, якщо сталася помилка кодування. Таким чином, вихідне значення, що закінчується нулем, було повністю записано тоді і тільки тоді, коли повернене значення невід'ємне і менше ніж n
.
З одного боку речення
В іншому випадку вихідні символи після n-1
st відкидаються, а не записуються в масив, а нульовий символ записується в кінці символів, фактично записаних в масив
говорить, що
якщо ( s
вказує на масив довжиною 3 символи, і) n
дорівнює 3, тоді будуть записані 2 символи, а символи, що перебувають поза 2-м, відкидаються ; тоді нульовий символ пишеться після цих 2 (а нульовим символом буде 3-й символ) .
І це, я вважаю, відповідає на вихідне питання.
ВІДПОВІДЬ:
Якщо копіювання відбувається між об’єктами, що перекриваються, поведінка не визначена.
Якщо n
дорівнює 0, тоді у вихідні дані нічого не записується
, якщо помилок кодування не виявлено, вихідні дані ЗАВЖДИ закінчуються нулем ( незалежно від того, чи вміщується вихідний масив у вихідному масиві чи ні ; якщо ні, то деякі символи відкидаються таким чином, що вихідні дані масив ніколи не переповнюється),
інакше (якщо трапляються помилки кодування) вихідні дані можуть не закінчуватись із нулем .
З іншого боку
Останнє речення
Таким чином, вихідне значення, що закінчується нулем, було повністю записано тоді і тільки тоді, коли повернене значення невід'ємне і менше ніж n
дає неоднозначність (або моя англійська мова недостатньо хороша). Я можу інтерпретувати це речення принаймні двома способами:
1. Вихідне значення закінчується нулем тоді і лише тоді, коли повернене значення є невід'ємним і меншеn
(що означає, що якщо повернене значення не менше n
, тобто вихід (включаючи закінчується нульовим символом) не вміщується в масив, тоді вихід не закінчується нулем ).
2. Вивід завершено (жоден символ не відкинуто) тоді і лише тоді, коли повернене значення невід’ємне і менше ніжn
.
Я вважаю, що інтерпретація 1 вище суперечить ВІДПОВІДІ, викликає нерозуміння та тривалі дискусії. Ось чому останнє речення, що описує snprintf
функцію, потребує змін, щоб усунути будь-яку неясність (що дає підстави для написання Пропозиції до мовного стандарту С).
Приклад недвозначного формулювання, на мою думку, можна взяти з http://en.cppreference.com/w/c/io/fprintf (див. 4)
), Завдяки @ "Martin Ba" за посилання.
Дивіться також запитання " snprintf: Чи є якісь стандартні пропозиції C / плани змінити опис цієї функції? ".