1

I am implementing a printf(const char * format, ...) like method for a class, where I need to determine the exact size of it's output given only the supplied format and the arguments given in va_list, before calling vsprintf() to perform the actual writing.

Is there a function that can take the format and va_list to generate the exact length of the output?

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
Anne Quinn
  • 12,609
  • 8
  • 54
  • 101
  • va_list is extremely error prone in that it will let users pass an elephant when an integer is expected and not indicate any failure, but instead enter the land of UDB, usually with very bad outcome. It completely relies on the format specifier for the type and size assumptions and does the equivalent of a reinterpret_cast. If you are in a C++ shop, I'd highly recommend using a more type safe means to your ends. These C-isms exist for backwards compatibility. Don't pollute your shiny new code with void pointer abuse and UDB – Christopher Pisz Sep 16 '18 at 01:44
  • @ChristopherPisz Every code is somehow _error prone_ if you don't know how to do it correctly. Do you have a better proposal how to use it without variadic parameters? – πάντα ῥεῖ Sep 16 '18 at 02:08
  • @πάνταῥεῖ There is error prone and then there is plain ignoring type safety altogether. However, I'd argue that not everything is error prone at _runtime_, even if you don't use it correctly. Compile time, sure...and that is our goal, to catch errors when they are the least expensive to fix. || What do you want me to propose? OP didn't mention his actual goal beyond providing a method that uses a variadic argument list. I told him he shouldn't. For a alternate solution, he would need to explain why he wants to do so, what kinds of things he imagines he will pass, and what he will do with them. – Christopher Pisz Sep 16 '18 at 02:42
  • @ChristopherPisz Well, thee are things like static analysis inspectors to help you healing these kinds of flaws. – πάντα ῥεῖ Sep 16 '18 at 02:50
  • 1
    @ChristopherPisz - My goal is to write a printf() like method for a class that logs debug messages. I enjoy the feel and flexibility of printf(), and it's actually replacing an iostream like << string building system that I greatly dislike. – Anne Quinn Sep 16 '18 at 03:11
  • @πάνταῥεῖ static analysis inspectors will not catch your variadic_list UDB. If you have one that does. message it to me and I will buy it promptly. static analysis has no idea what you intend with reinterpret casts, nor does the compiler. That's the basis for them being unsafe and ill recommended. All bugs appear at runtime and maybe in ways that are not immediately detected. Bad news for your business! I've seen more than one law suit from using variadic args in critical software. – Christopher Pisz Sep 16 '18 at 03:21
  • @AnneQuinn What do you "greatly dislike" about using type safe streams in C++ and are you using them correctly? Also, are you even using C++ or are you using C? You've tagged both for some reason. – Christopher Pisz Sep 16 '18 at 03:21
  • 1
    @Christohper There are a lot of draw backs and flaws about the `<<` operator style, let convenient international translations with different needs of word positions alone. Otherwise there won't be any need of the [The Boost Format library](https://www.boost.org/doc/libs/1_66_0/libs/format/doc/format.html) – πάντα ῥεῖ Sep 16 '18 at 03:29
  • @πάνταῥεῖ Feel free to start a chat and point them out to me. You are most likely not using them correctly. I just recently had a discussion with a nice fellow on the C++ standards committee about this very topic and he swayed me to be pro streams. There are an aweful lot of myths and folklore out there when it comes to C-style vs C++ streams. – Christopher Pisz Sep 16 '18 at 03:35
  • @ChristopherPisz I don't like to start that decades old discussion again. All of the arguments were discussed well already. Regarding this particular question my answer is quite straightforward, regardless if you like the style or not. – πάντα ῥεῖ Sep 16 '18 at 03:43
  • @ChristopherPisz - I like to format my output and using << arguments can make it really verbose to do so, I feel it's just a matter of preference, and I'm happy giving up type safety for it. C++ is tagged because that's technically the language I'm using. C is tagged (and I mean this benignly, I don't want to start a discussion) because I wanted to avoid answers that try to guess what I "really want" to avoid the C library. I really just want to use vsprintf() and that's it. – Anne Quinn Sep 16 '18 at 03:46
  • @AnneQuinn I'm not sure how ' stream << thing' is more 'verbose' than 'sprintf( buffer,"%d", thing);' We could count characters... Well, good luck to you! – Christopher Pisz Sep 16 '18 at 03:55
  • @πάνταῥεῖ Undefined behavior is not a style. Also, I'm not in the comment section of your answer currently. If you don't want to discuss the supposed "drawbacks" (that are likely your own misunderstanding of how to use streams properly), then please don't go propagating the idea that they exist in places where impressionable people are looking for expert advise. – Christopher Pisz Sep 16 '18 at 03:59

1 Answers1

5

As from the example in the documentation, you can determine the necessary buffer size 1st (emphasis mine):

std::vector<char> buf(1+std::vsnprintf(NULL, 0, fmt, args1)); // <<<
va_end(args1);
std::vsnprintf(buf.data(), buf.size(), fmt, args2);

4) Writes the results to a character string buffer. At most buf_size-1 characters are written. The resulting character string will be terminated with a null character, unless buf_size is zero. If buf_size is zero, nothing is written and buffer may be a null pointer, however the return value (number of bytes that would be written not including the null terminator) is still calculated and returned.

Generally all variants of the <x>sprintf() functions family can be used to calculate the necessary buffer size if the target buffer parameter is passed as NULL or nullptr.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190