I have a function formatToStr()
which receives a format in const std::string&
and returns the formatted string.
#include <string>
#include <cstdarg>
std::string formatToStr(const std::string& format, ...) {
char buff[1024];
va_list args;
va_start(args, format.c_str());
vsnprintf(buff, sizeof(buff), format.c_str(), args);
va_end(args);
return std::string(buff);
}
int main() {
printf("Testing: %s\n", formatToStr(std::string("test")).c_str());
return 0;
}
This code compiles with a warning:
$ g --version
g (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
...
$ g ./c.cpp
./c.cpp: In function ‘std::string formatToStr(const string&, ...)’:
./c.cpp:8:9: warning: second parameter of ‘va_start’ not last named argument [-Wvarargs]
8 | va_start(args, format.c_str());
| ^~~~~~~~
When changing format
type to const char*
there's no warning.
Why is that?
Thanks.
CodePudding user response:
You slightly misinterpret the error message. The culprit is not the last named argument
but the second parameter
: format.c_str()
is not format
. va_start
is a macro, it needs the name of the last named argument.
However, as mentioned in comments, va_start(args,format)
would be wrong too, because you may not use a reference here, see https://timsong-cpp.github.io/cppwp/n4868/cstdarg.syn#1.sentence-4. It is undefined. Some compilers diagnose it (but others dont). You could use a string_view
passed by value.
Last but not least, va_args
is basically outdated since C 11 introduced variadic templates. And for formatting of strings via %s
-like formatters you should take a look at <format>
.