Updates to documentation for string printf functions#3328
Conversation
…nt is zero, len is returned as the count of characters required to format the output (not including the terminating null). * Clarify that [v]snprintf() will not attempt to truncate a zero-character formatted data string when count = 0, by placing a null-terminator at buffer[-1]. * Clarify that for functions other than [v]snprintf(), if len > count and buffer is a null pointer, then either len will be returned - without error - if count is zero, or the invalid parameter handler will be invoked if count is nonzero.
…mily of functions.
…nwprintf_s()/_vsnwprintf_s().
…tion has occurred.
|
@adr26 : Thanks for your contribution! The author(s) have been notified to review your proposed change. |
|
I have incorrectly conflated the documentation on encoding errors (for wide string function variants) with the errors that can occur during formatting. From the C specification:
I will add a new test case for this to my test code, update the documentation accordingly and re-open the PR. Sorry for the confusion. Thanks, Andrew R |
|
I added test cases to my test code to examine the behaviour of the various families of In all cases, I have updated the PR description, plus updated the documentation accordingly — having also rebased to the latest code from the main Please let me know if you've any questions on what I've done. Thanks, Andrew R |
|
Ah, alas — GitHub won't let me re-open this PR! I will set up a new one... |
|
I can't reopen it either. I'll watch for your new one. |
|
Thanks @tycastMSFT — I've opened a new PR: #3411, where I've rolled in my corrected descriptions of the handling of encoding errors. I realise that it'll need dev review, and there may be a discussion of to what extent you want to codify the current encoding-error-handling behaviour, but hopefully my changes to the docs are an accurate description of the current CRT behaviour and will serve as a useful basis for discussing how the docs should be updated (and may perhaps even be able to be accepted wholesale!) Andrew R |
|
@TylerMSFT Do you not see a "Reopen and comment" button at the bottom of a comment box like this one? There may be other ways to reopen a PR, but this one is how I usually do it. If you don't, then maybe I didn't set up your admin privileges correctly. |
|
@corob-msft - I see the button but it won't respond, i.e. it's not clickable. |
|
Hi @corob-msft, @TylerMSFT, Please ignore #3328 (I think github refuses to allow you to re-open a PR if you force-pushed, which I did to my repo once I'd rebased my changes with up-to-date changes from the MicrosoftDocs repo). Instead, please look at my new PR: #3411, where I've rolled in my corrected descriptions of the handling of encoding errors. I realise that the PR will need dev review, and there may be a discussion of to what extent you want to codify the current encoding-error-handling behaviour, but hopefully my changes to the docs in #3411 are an accurate description of the current CRT behaviour and will serve as a useful basis for discussing how the docs should be updated (and may perhaps even be able to be accepted wholesale!) Andrew R |
|
@adr26 Don't worry, we'll work with your latest PR. We're just curious why one of our buttons doesn't work as expected. There's hover text associated with the button: "There is already an open pull request from adr26:master to MicrosoftDocs:master". It may be that you can only have one open PR from a particular branch at a time? I bet that's it. |
The behaviour of
vsnprintf()withcount == 0andbuffer != NULLis to return the length of the formatted data, rather than returning-1— as the documentation currently states. I have cross-referenced the behaviour ofvsnprintf()with the C specification, and confirmed that the implementation behaviour (returning the length of the formatted data) conforms to the C specification and is correct. Therefore, the currentvsnprintf()documentation is incorrect and needs to be updated.After making this observation, I conducted a broader review of the documentation for the
*sn[w]printf*family of functions, making these updates as a result.In general, I've corrected a number of errors in the description of the behaviour of the
*sn[w]printf*family of functions, and have aligned the information for:_snprintf_s()/_snwprintf_s()and_vsnprintf_s()/_vsnwprintf_s()snprintf()/_snprintf()/_snwprintf()andvsnprintf()/_vsnprintf()/_vsnwprintf()A detailed description of the problems addressed on each page is given below:
_snprintf_s()/_snwprintf_s():Add description of behaviour which occurs when an encoding error occurs during formatting — setting
errnotoEILSEQin all cases and either returning a negative value for a string conversion specifier, or skipping the character for a character conversion specifier.Clarify that in cases where truncation does not occur, null-termination is performed
Clarify truncation behaviour:
count < sizeOfBuffer, but formatted data> count, then formatted data is truncated tocountcharacters, null-terminated and -1 is returned with no error handler / update toerrnocount == _TRUNCATE, and formatted data>= sizeOfBuffer, then formatted data is truncated to(sizeOfBuffer - 1)characters, null-terminated and -1 is returned with no error handler / update toerrnocount >= sizeOfBuffer, formatted data>= sizeOfBuffer, andcount != _TRUNCATE, the invalid parameter handler is invoked. If continued, the functions truncate the buffer to an empty string, return -1 and seterrnotoERANGEClarify error handling behaviour:
bufferisNULL, anEINVALerror occurs if (and only if) eithercountorsizeOfBufferare!= 0(if both are 0, no error occurs and 0 is returned)EINVALerror does not occur in all cases wherecount == 0, only when one of the other conditions are met (countcannot be negative, assize_tis unsigned)sizeOfBuffer(notcount!)== 0, and additionally if buffer is notNULL, then anEINVALerror occursAdd copy of error conditions table from
_vsnprintf_s()/_vsnwprintf_s().snprintf()/_snprintf()/_snwprintf():Add description of behaviour which occurs when an encoding error occurs during formatting — setting
errnotoEILSEQin all cases and either returning a negative value for a string conversion specifier, or skipping the character for a character conversion specifier.Clarify truncation behaviour:
snprintf(), clarify that null-termination by writing tobuffer[count-1]is only performed ifcount != 0._snprintf()/_snwprintf(), clarify that non-terminated truncation is performed only whenbuffer != NULL(ifbuffer == NULLandcount != 0, it is an error and if ifbuffer == NULLandcount == 0, the length of the formatted data is returned)._vsnprintf_s()/_vsnwprintf_s():Add description of behaviour which occurs when an encoding error occurs during formatting — setting
errnotoEILSEQin all cases and either returning a negative value for a string conversion specifier, or skipping the character for a character conversion specifier.Clarify that in cases where truncation does not occur, null-termination is performed
Clarify truncation behaviour:
count >= sizeOfBufferand formatted data>= sizeOfBuffer, then only if alsocount != _TRUNCATEthe invalid parameter handler is invoked, etc.Clarify error handling behaviour:
bufferisNULL, anEINVALerror occurs if (and only if) eithercountorsizeOfBufferare!= 0(if both are 0, no error occurs and 0 is returned)EINVALerror does not occur in all cases wherecount == 0, only when one of the other conditions are met (countcannot be negative, assize_tis unsigned)sizeOfBuffer(notcount!)== 0, and additionally if buffer is notNULL, then anEINVALerror occursUpdate error conditions table to correct from
count == 0tosizeOfBuffer == 0as the condition required for anEINVALerror (whenbuffer != NULL).vsnprintf()/_vsnprintf()/_vsnwprintf():Add description of behaviour which occurs when an encoding error occurs during formatting — setting
errnotoEILSEQin all cases and either returning a negative value for a string conversion specifier, or skipping the character for a character conversion specifier.Clarify that in cases where truncation does not occur, null-termination is performed
Clarify truncation behaviour:
vsnprintf(), clarify that null-termination by writing tobuffer[count-1]is only performed ifcount != 0._vsnprintf()/_vsnwprintf(), clarify that non-terminated truncation is performed only whenbuffer != NULL(ifbuffer == NULLandcount != 0, it is an error and if ifbuffer == NULLandcount == 0, the length of the formatted data is returned).vsnprintf(), clarify that ifcount == 0andbuffer != NULL, the length of the formatted data is returned, rather than-1(as is the case for_vsnprintf()/_vsnwprintf()).To verify the behaviour of these functions, I constructed the attached test code (printf.zip). The updated descriptions of these functions' behaviour can be verified using the output from this: