Is snprintf always null terminating the destination buffer?
In other words, is this sufficient:
char dst[10];
snprintf(dst, sizeof (dst), "blah %s", somestr);
or do you have to do like this, if somestr is long enough?
char dst[10];
somestr[sizeof (dst) - 1] = '\0';
snprintf(dst, sizeof (dst) - 1, "blah %s", somestr);
I am interested both in what the standard says and what some popular libc might do which is not standard behavior.
The ambiguity starts from the C Standard itself. Both C99 and C11 have identical description of
snprintf
function. Here is the description from C99:On the one hand the sentence
says that
if (the
s
points to a 3-character-long array, and)n
is 3, then 2 characters will be written, and the characters beyond the 2nd one are discarded; then the null character is written after those 2 (and the null character will be the 3rd character written).And this I believe answers the original question.
THE ANSWER:
If copying takes place between objects that overlap, the behavior is undefined.
If
n
is 0 then nothing is written to the outputotherwise, if no encoding errors encountered, the output is ALWAYS null-terminated (regardless of whether the output fits in the output array or not; if not then some characters are discarded such that the output array is never overflown),
otherwise (if encoding errors are encountered) the output can stay non-null-terminated.
On the other hand
The last sentence
gives ambiguity (or my English is not good enough). I can interpret this sentence in at least two ways:
1. The output is null-terminated if and only if the returned value is nonnegative and less than
n
(which means that if the returned value is not less thann
, i.e. the output (including the terminating null character) does not fit in the array, then the output is not null-terminated).2. The output is complete (no characters have been discarded) if and only if the returned value is nonnegative and less than
n
.I believe that the interpretation 1 above contradicts THE ANSWER, causes misunderstanding and lengthy discussions. That is why the last sentence describing the
snprintf
function needs a change in order to remove any ambiguity (which gives grounds for writing a Proposal to the C language Standard).The example of non-ambiguous wording I believe can be taken from http://en.cppreference.com/w/c/io/fprintf (see
4)
), thanks to @"Martin Ba" for the link.See also the question "snprintf: Are there any C Standard Proposals/plans to change the description of this func?".
As the other answers establish: It should:
So all you have to take care is that you don't pass an zero-size buffer to it, because (obviously) it cannot write a zero to "nowhere".
However, beware that Microsoft's library
does not have a function calledhistorically only had a function calledsnprintf
but instead_snprintf
(note leading underscore) which does not append a terminating null. Here's the docs (VS 2012, ~~ VS 2013):http://msdn.microsoft.com/en-us/library/2ts7cx93%28v=vs.110%29.aspx
Visual Studio 2015 (VC14) apparently introduced the conforming
snprintf
function, but the legacy one with the leading underscore and the non null-terminating behavior is still there:According to snprintf(3) manpage.
So, yes, no need to terminate if size >= 1.
According to the C standard, unless the buffer size is 0,
vsnprintf()
andsnprintf()
null terminates its output.So, if you need to know how big a buffer to allocate, use a size of zero, and you can then use a null pointer as the destination. Note that I linked to the POSIX pages, but these explicitly say that there is not intended to be any divergence between Standard C and POSIX where they cover the same ground:
Be wary of the Microsoft version of
vsnprintf()
. It definitely behaves differently from the standard C version when there is not enough space in the buffer (it returns -1 where the standard function returns the required length). It is not entirely clear that the Microsoft version null terminates its output under error conditions, whereas the standard C version does.Note also the answers to Do you use the TR 24731 safe functions? (see MSDN for the Microsoft version of the
vsprintf_s()
) and Mac solution for the safe alternatives to unsafe C standard library functions?Some older versions of SunOS did weird things with snprintf and might have not NUL-terminated the output and had return values that didn't match what everyone else was doing, but anything that has been released in the past 10 years have been doing what C99 says.