Namespaces
Variants
Views
Actions

Talk:c/io/fprintf

From cppreference.com
< Talk:c‎ | io
Revision as of 05:28, 26 February 2015 by Oli (Talk | contribs)

snprintf(0,0,format,...) seems correct and used to know the required buffer size

In this page and also in C++ documentation, the specific usage of snprintf(nullptr,0,format,...) and std::snprintf(nullptr,0,format,...) is not documented.

I have done some testing on coliru using compilation options g++ -std=c++14 -pedantic -g -Wall -Wextra -Wvla (see above snippet).

But I do not know if this is a standard. I have read on stackoverflow that on Windows, this does not work and the recommended way is to use _scprintf...

Do you agree if I update the documentation?

--Oli (talk) 08:45, 20 February 2015


#include <iostream>
#include <stdio.h>
 
int main()
{
    size_t size;
 
    std::cerr <<"\n" "Calling snprintf(0,0,...)"<< std::endl;
    size =      snprintf( 0, 0, "This is the string [%s] and this is the integer [%d]", "blablabla", 12345 );
    std::cerr <<"size="<< size << std::endl;
 
    std::cerr <<"\n" "Calling std::snprintf(0,0,...)"<< std::endl;
    size = std::snprintf( 0, 0, "This is the string [%s] and this is the integer [%d]", "blablabla", 12345 );
    std::cerr <<"size="<< size << std::endl;
 
    // ISO C++14 seems to accept variable length array 'buffer' [-Wvla]
    char buffer[ size +1 ]; // +1 for NUL termination byte 
 
    std::cerr <<"\n" "Calling std::snprintf(buffer,size,...)"<< std::endl;
    size = std::snprintf( buffer, size+1, "This is the string [%s] and this is the integer [%d]", "blablabla", 12345 );
    std::cerr <<"size="<< size << std::endl;
    std::cerr <<"buffer="<< buffer << std::endl;
 
    std::cerr <<"\n" "Calling std::sprintf(buffer,...)"<< std::endl;
    size = std::sprintf( buffer, "This is the string [%s] and this is the integer [%d]", "blablabla", 12345 );
    std::cerr <<"size="<< size << std::endl;
    std::cerr <<"buffer="<< buffer << std::endl;
 
    // Segmentation fault using std::sprintf(0,...)
    // same for ::sprintf(0,...)
 
    std::cerr <<"\n" "Calling std::sprintf(0,...)"<< std::endl;
    size = std::sprintf( 0, "This is the string [%s] and this is the integer [%d]", "blablabla", 12345 );
    std::cerr <<"size="<< size << std::endl;
}

Output:

g++ -std=c++14 -pedantic -g -Wall -Wextra -Wvla main.cpp && ./a.out
 
main.cpp: In function 'int main()':
main.cpp:17:26: warning: variable length array 'buffer' is used [-Wvla]
     char buffer[ size +1 ]; // +1 for NUL termination byte 
                          ^
 
Calling snprintf(0,0,...)
size=62
 
Calling std::snprintf(0,0,...)
size=62
 
Calling std::snprintf(buffer,size,...)
size=62
buffer=This is the string [blablabla] and this is the integer [12345]
 
Calling std::sprintf(buffer,...)
size=62
buffer=This is the string [blablabla] and this is the integer [12345]
 
Calling std::sprintf(0,...)
bash: line 7: 28976 Segmentation fault      (core dumped) ./a.out
yes, this is standard behavior, and this page currently mentions it by stating that snprintf returns "number of characters (not including the terminating null character) which would have been written to buffer if bufsz was ignored". I'll add a note. --Cubbi (talk) 08:54, 20 February 2015 (PST)
Hi Cubbi, your edit is fine.
However I am sorry for having suggested the line char buf[sz + 1];
This is the Variable Length Array standardized in C99 BUT not (yet?) in C++.
The VLA was planned to be introduced in C++14 as Runtime-sized arrays with automatic storage duration but has been out-scoped because of lack of runtime computation of sizeof(buf)
VLA maybe or not introduced in C++17
Therefore I try to think about an alternative C++ compliant as char *buf = new char[sz + 1];
What do you think? Oli (talk) 05:28, 26 February 2015 (PST)