Starting at what version of Visual Studio is vsnprintf mostly standard-conformant?
<p>According to <a href="https://msdn.microsoft.com/en-us/library/1kt27hek.aspx" rel="noreferrer">Microsoft's documentation for <code>vsnprintf</code></a>, that function is part of the C(++) Run-Time Library since at least the 2003 edition of Visual Studio.</p>
<pre><code>int vsnprintf( char *buffer,        // Storage location for output
               size_t count,        // Maximum number of characters to write
               const char *format,  // Format specification
               va_list argptr )     // Pointer to list of other arguments
</code></pre>
<p>I'm asking: for which versions of Visual Studio is the <code>vsnprintf</code> implementation of the bundled C(++) RTL for x86 and x64 in conformance with the C99 standard (ISO/IEC 9899:1999), assuming</p>
<ul>
<li><code>#define _CRT_SECURE_NO_WARNINGS</code> is performed before <code>#include &lt;stdio.h&gt;</code>, which is required for modern versions of Visual Studio RTL;</li>
<li>if <code>count</code> is greater than zero, then <code>buffer</code> is a pointer to (at least) <code>count</code> writable characters;</li>
<li>format is not <code>NULL</code> and conforms to <a href="https://msdn.microsoft.com/en-us/library/56e442dc.aspx" rel="noreferrer">Microsoft's Format Specification syntax</a> as applicable to the particular version of the RTL;</li>
<li>the value of <code>count</code> and the number of characters to produce are both small enough to fit type <code>int</code>;</li>
</ul>
<p>and we want conformance to include (beside basic functionality for nominal input) these requirements (implied by the standard's specification of <code>snprintf</code>, which <code>vsnprintf</code> references):</p>
<ol>
<li>not producing undefined behavior (including invoking <a href="https://msdn.microsoft.com/en-us/library/ksazx244.aspx" rel="noreferrer">Microsoft's invalid parameter handler</a>) under the above assumptions;</li>
<li>returning the length to be written (not including terminating null character) when <code>buffer==NULL</code> and <code>count==0</code>, thus allowing pre-flight to determine the length of the output;</li>
<li>always padding the output string with a terminating null character when <code>buffer!=NULL</code> and <code>count&gt;0</code> and the result returned is non-negative, including for truncated output due to small <code>count</code>.</li>
</ol>
<p>Note following <a href="https://stackoverflow.com/q/34996375/903600#comment57721538_34996375">comment</a>: I'm willing to admit the lack of <code>restrict</code> qualifiers as still within allowance for mostly standard-conformant.</p>
<hr />
<p>The documentation leaves conformance ambiguous with respect to (3.); the implementation bundled with Visual Studio Community 2015 is fine as far as I can tell, but not all are.</p>
<blockquote>
<p>If there is room at the end (that is, if the number of characters to write is less than <code>count</code>), the buffer will be null-terminated.</p>
</blockquote>
<p>The documentation also has wording unambiguously implying that <code>vsnprintf</code> is not in conformance with the C99 standard with respect to (1.) and (2.) when <code>buffer==NULL</code> and <code>count==0</code> ; but theses parts of the documentation seemingly turn out to be wrong:</p>
<blockquote>
<p>if the number of characters to write is greater than <code>count</code>, these functions return -1 indicating that output has been truncated.</p>
<p>If <code>buffer</code> or <code>format</code> is <code>NULL</code>, or if <code>count</code> is less than or equal to zero, these functions invoke the invalid parameter handler</p>
</blockquote>
<hr />
<p>Test code:</p>
<pre><code>#define _CRT_SECURE_NO_WARNINGS
#include &lt;stdio.h&gt;
#include &lt;stdarg.h&gt;

int f( char *buffer,
       size_t count,
       const char *format,
       ...
     )
{
    va_list vArgs;
    int vRes;
    va_start(vArgs, format);
    vRes = vsnprintf( buffer, count, format, vArgs);
    va_end(vArgs);
    return vRes;
}

int main(void)
{
    char vBuf[6];
    int j, count;
#ifdef _MSC_VER
    printf(&quot;_MSC_VER = %ld\n&quot;,(long)(_MSC_VER));
#else
    printf(&quot;_MSC_VER is undefined\n&quot;);
#endif
    printf(&quot;f(NULL,0,\&quot;%%d\&quot;,777):%3d\n&quot;, f(NULL,0,&quot;%d&quot;,777));
    for(count=0 ;count&lt;=sizeof(vBuf); ++count)
    {
        for(j=0; j&lt;sizeof(vBuf)-1; ++j)
            vBuf[j] = '!';
        vBuf[j] = 0;
        j =  f(vBuf,count,&quot;%d&quot;,777);
        printf(&quot;f(vBuf,%d,\&quot;%%d\&quot;,777):%3d  vBuf: \&quot;%s\&quot;\n&quot;,count,j,vBuf);
    }
    return 0;
}
</code></pre>
<p>giving under my install of Visual Studio Community 2015</p>
<pre><code>_MSC_VER = 1900
f(NULL,0,&quot;%d&quot;,777):  3
f(vBuf,0,&quot;%d&quot;,777):  3  vBuf: &quot;!!!!!&quot;
f(vBuf,1,&quot;%d&quot;,777):  3  vBuf: &quot;&quot;
f(vBuf,2,&quot;%d&quot;,777):  3  vBuf: &quot;7&quot;
f(vBuf,3,&quot;%d&quot;,777):  3  vBuf: &quot;77&quot;
f(vBuf,4,&quot;%d&quot;,777):  3  vBuf: &quot;777&quot;
f(vBuf,5,&quot;%d&quot;,777):  3  vBuf: &quot;777&quot;
f(vBuf,6,&quot;%d&quot;,777):  3  vBuf: &quot;777&quot;
</code></pre>
<p>and under some install of Visual Studio 2008 (I believe SP1 + PSDK 7.1)</p>
<pre><code>_MSC_VER = 1500
f(NULL,0,&quot;%d&quot;,777):  3
f(vBuf,0,&quot;%d&quot;,777): -1  vBuf: &quot;!!!!!&quot;
f(vBuf,1,&quot;%d&quot;,777): -1  vBuf: &quot;7!!!!&quot;
f(vBuf,2,&quot;%d&quot;,777): -1  vBuf: &quot;77!!!&quot;
f(vBuf,3,&quot;%d&quot;,777):  3  vBuf: &quot;777!!&quot;
f(vBuf,4,&quot;%d&quot;,777):  3  vBuf: &quot;777&quot;
f(vBuf,5,&quot;%d&quot;,777):  3  vBuf: &quot;777&quot;
f(vBuf,6,&quot;%d&quot;,777):  3  vBuf: &quot;777&quot;
</code></pre>
<p>Notice the lack of terminating null character in particular for <code>count==3</code>, even though the output is positive.</p>