For VC6 C Users (not C++)
1. Explanation
You can't. You have to:
Guess a buffer size yourself.
Make a buffer that is large enough (which is not easy), then you can get a correct buffer size. See below.
snprintf enters the standard library in C99, and is not present in VC6. All you have is a _snprintf, which:
Returns -1 if the number of characters to write is less than or equal to count`. So can't be used to get the buffer size.
This seems not documentated (see Microsoft Docs). But _vsnprintf has special behavior in the same situation, so I guess there may be something here and with the test below I found my assumption correct.
Yes, it even doesn't return the number of characters it has written, like _vsnprintf. Just a -1.
This one is documentated: If buffer is a null pointer and count is nonzero, or if format is a null pointer, the invalid parameter handler is invoked, as described in Parameter Validation. invalid parameter handler is invoked means you will get a segmentation fault.
Test code here:
#includeintmain(void){chars[100],s1[100]={0};#defineTEST(s)printf("%s: %d\n",#s, s)TEST(_snprintf(NULL,0,"%d",12345678));/* Tested, and segmentation Fault */// TEST(_snprintf(NULL, 100, "%d", 12345678));TEST(_snprintf(s,0,"%d",12345678));TEST(_snprintf(s,100,"%d",12345678));TEST(_snprintf(s1,5,"%d",12345678));puts(s);puts(s1);return0;}
And the output with VC6 compiler:
_snprintf(NULL,0,"%d",12345678):-1_snprintf(s,0,"%d",12345678):-1_snprintf(s,100,"%d",12345678):8_snprintf(s1,5,"%d",12345678):-11234567812345
which supports my assumption.
Note that when the count argument passed in is smaller than the actual string length to write, though _snprintf returns -1, it will actually write count characters into the buffer.
2. Write one yourself with va_list? No way!
snprintf enters the standard library in C99, and there is no snprintf, _vsnprintf and __vscprintf:
asprintf.obj :error LNK2001:unresolved external symbol _vsnprintf
asprintf.obj :error LNK2001:unresolved external symbol __vscprintf
So you can't use the va_list implementation in one of the answers.
3. _vsnprint & _snprintf: Present but Absent
Actually, _vsnprintf is present. If you try to call it, you can make it.
You may say, there is a contradictory, you just said unresolved external symbol _vsnprintf. This is weird, but it's true. The _vsnprintf in unresolved external symbol _vsnprintf is not the one your code links to if you writes _vsnprintf directly.
Same thing happens on _snprintf. You can call it yourself, but you if you call snprintf, the linker will complain that there is no _snprintf.
4. Get the buffer size to write by passing 0 argument as count like we do in *nix? No way!
What's worse, you can't write this for yourself:
size_tnbytes =snprintf(NULL,0,fmt,__VA_ARGS__)+1;/* +1 for the '\0' */char*str =malloc(nbytes);snprintf(str,nbytes,fmt,__VA_ARGS__);
That's because:
As explained above, there is no snprintf in VC6.
As explained above, you can replace snprintf with _snprintf and compile it successfully. But since you passed NULL, you will get a segmentation fault.
Even if for some reason your program not crashed, nbytes will be -1 since you passed 0. And size_t is usually unsigned, so -1 will become a large number, like 4294967295 in an x86 machine, and your program will stop in the next malloc step .
5. Maybe an elegant solution
You can link a library called legacy stdio definitions or something else, but I choose to guess the buffer size myself, since in my case it is not very dangerous to do that.