Неопределенность начинается с самого стандарта 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 записывается нулевой символ (и третьим символом будет записан нулевой символ) .
И это, я полагаю, отвечает на первоначальный вопрос.
ОТВЕТ:
Если копирование происходит между объектами, которые перекрываются, поведение не определено.
Если n
равно 0, то на выход ничего не записывается
в противном случае, если ошибок кодирования не обнаружено, вывод ВСЕГДА заканчивается нулем ( независимо от того, помещается ли вывод в выходной массив или нет ; если нет, то некоторые символы отбрасываются так, что выходной массив никогда не переполняется),
в противном случае (если обнаружены ошибки кодирования), вывод может остаться не завершенным нулем .
С другой стороны
Последнее предложение
Таким образом, завершенный нулем вывод был полностью записан тогда и только тогда, когда возвращаемое значение неотрицательно и меньше n
дает двусмысленность (или мой английский недостаточно хорош). Я могу интерпретировать это предложение по крайней мере двумя способами:
1. Выходное значение равно с нулевым символом в конце тогда и только тогда, когда возвращаемое значение неотрицательно и меньше n
(что означает, что если возвращаемое значение равно , а не меньше n
, т. е. выходные данные (включая завершающий нулевой символ) не помещаются в массив, тогда выходные данные не заканчиваются нулем ).
2. Выходные данные complete (никакие символы не были отброшены) тогда и только тогда, когда возвращаемое значение неотрицательно и меньше n
.
Я полагаю, что приведенное выше толкование 1 противоречит ОТВЕТУ, вызывает недопонимание и длительные дискуссии. Вот почему последнее предложение, описывающее функцию snprintf
, нуждается в изменении, чтобы устранить любую двусмысленность (что дает основание для написания предложения к стандарту языка Си).
Я полагаю, что пример недвусмысленной формулировки можно взять из http://en.cppreference.com/w/c/io/fprintf (см. 4)
), спасибо @ "Martin Ba" за ссылку.
См. Также вопрос « snprintf: Существуют ли какие-либо Стандартные предложения / планы C по изменению описания этой функции? ».