Is snprintf () ALWAYS a null termination?

Is snprintf always the null termination of the destination buffer?

In other words, is this enough:

char dst[10]; snprintf(dst, sizeof (dst), "blah %s", somestr); 

or do you need to do 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 in what the standard says, as well as what some popular libc can do, which is not standard behavior.

+61
c posix libc
Oct 09 '11 at 10:18
source share
5 answers

How other answers set::

snprintf ... Writes the results to the character string buffer. (...) will be terminated with a null character if buf_size is not equal to zero.

So all you have to take care of is that you do not pass it a null buffer, because (obviously) it cannot write zero to "nowhere."




However, beware that there is no function in the Microsoft library called snprintf , but instead, historically, there was only a function called _snprintf (note the underscore), which makes it not _snprintf add a terminating zero. Here's the docs (VS 2012, ~~ VS 2013):

http://msdn.microsoft.com/en-us/library/2ts7cx93%28v=vs.110%29.aspx

Return value

Let len โ€‹โ€‹be the length of the formatted data string (not including the terminating zero). len and count in bytes for _snprintf, wide characters for _snwprintf.

  • If len <count, then len characters are stored in the buffer, and null-terminator is added and len is returned.

  • If len = count, then len characters are stored in the buffer, no null-terminator is added, and len is returned.

  • If len> count, then the counters are stored in the buffer, no null-terminator is added, and a negative value is returned.

(...)

Visual Studio 2015 (VC14) appears to have introduced a compatible snprintf function, but the former with leading underscore and non-null ending behavior still exists

The snprintf function truncates output when len is greater than or equal to the count, placing a null terminator in buffer[count-1] . (...)

For all functions other than snprintf , if len = count, len characters are stored in a buffer, a null terminator is not added, (...)

+55
Oct 25
source share

According to snprintf (3) manpage.

The functions snprintf() and vsnprintf() are written no more than size bytes (including the trailing zero byte ('\ 0')) before str .

So yes, no need to terminate if size> = 1.

+16
09 Oct '11 at 10:21
source share

According to the C standard, if the buffer size is not 0, vsnprintf() and snprintf() null completes its output.

The function snprintf() should be equivalent to sprintf() , with the addition of n arguments, which determines the size of the buffer referenced by s. If n is zero, nothing should be written and s may be a null pointer. Otherwise, output bytes that go beyond n-1 should be discarded instead of being written to the array, and a null byte is written at the end of the bytes actually written to the array.

So, if you need to know how big the buffer is allocated, use a zero size, and then you can use a null pointer as the destination. Note that I am related to POSIX pages, but they explicitly say that there is no discrepancy between the C standard and POSIX, where they cover the same basis:

The functionality described on this manual page complies with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This scope of POSIX.1-2008 is ISO C standard.

Be careful with the Microsoft version of vsnprintf() . It definitely behaves differently than the standard C version when there is not enough space in the buffer (it returns -1 when the standard function returns the required length). It is not clear that the version of Microsoft version completes its output under error conditions, whereas the standard version of C does.

Please also note the answers . Do you use the safe functions of the TR 24731? (see MSDN for Microsoft version vsprintf_s() ) and Mac for safe alternatives to the insecure functions of the C standard library?

+10
Oct 09 '11 at
source share

Some older versions of SunOS did strange things with snprintf and might not have NUL-finalized output and had return values โ€‹โ€‹that did not match what everyone else did, but everything that was released over the past 10 years was what C99 did.

+4
10 Oct 2018-11-11T00:
source share

The ambiguity begins with the C standard itself. Both C99 and C11 have the same snprintf function description. Here is a description with C99:

7.19.6.5 snprintf function
abstract
1 #include <stdio.h> int snprintf(char * restrict s, size_t n, const char * restrict format,...);
Description
2 The function snprintf equivalent to fprintf , except that the output is written to the array (specified by the s argument), and not to the stream. If n is zero, nothing is written, and s may be a null pointer. Otherwise, output characters outside of n-1 st are discarded, not written to the array, and the null character is written at the end of the characters actually written to the array. If copying occurs between overlapping objects, the behavior is undefined.
Returns
3 The snprintf function returns the number of characters that were written if n were large enough, not counting the terminating null character or a negative value if an encoding error occurred. Thus, null-terminated output was completely written if and only if the return value is non-negative and less than n .

On the one hand, the proposal

Otherwise, the output characters outside the n-1 1st are discarded, not written to the array, and the null character is written at the end of the characters actually written to the array

Says that
if ( s points to an array of 3 characters long and) n is 3, then 2 characters will be written, and characters outside the second will be discarded ; then the null character is written after these 2 (and the null character will be written in the third character).

And this, in my opinion, answers the original question.
ANSWER:
If copying occurs between overlapping objects, the behavior is undefined.
If n is 0, then nothing is written to the output
otherwise, if encoding errors are not encountered, the ALWAYS output terminates to zero (regardless of whether the output matches the output array or not, and if not, some characters are discarded, so the output array never overflows)
otherwise (if encoding errors are encountered), the output may remain non-zero.

On the other hand
The last sentence

Thus, null-terminated output was completely written if and only if the return value is non-negative and less than n

gives ambiguity (or my English is not good enough). I can interpret this sentence in at least two ways:
1. An output is completed with a zero value if and only if the return value is non-negative and less than n (this means that if the return value is not less than n , that is, the output (including the terminating null character) does not fit into the array, then the output does not end with zero )
2. The output is completed (not a single character has been discarded) if and only if the return value is non-negative and less than n .




I believe that interpretation 1 above contradicts the ANSWER, causes misunderstanding and lengthy discussions. This is why the last sentence describing the snprintf function needs to be changed to eliminate any ambiguity (which gives grounds for writing a sentence in the C language standard).
An example of an explicit statement, 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 standard C suggestions / plans to change the description of this function? ".

+2
May 23 '18 at 22:42
source share



All Articles