Lately, I noticed a strange case I would like to verify:
By SUS, for %n in a format string, the respective int will be set to the-amount-of-bytes-written-to-the-output.
Additionally, for snprintf(dest, 3, "abcd"), dest will point to "ab\0". Why? Because no more than n (n = 3) bytes are to be written to the output (the dest buffer).
I deduced that for the code:
int written;
char dest[3];
snprintf(dest, 3, "abcde%n", &written);
written will be set to 2 (null termination excluded from count).
But from a test I made using GCC 4.8.1, written was set to 5.
Was I misinterpreting the standard? Is it a bug? Is it undefined behaviour?
Edit:
@wildplasser said:
... the behavior of %n in the format string could be undefined or implementation defined ...
And
... the implementation has to simulate processing the complete format string (including the %n) ...
@par said:
writtenis 5 because that's how many characters would be written at the point the%nis encountered. This is correct behavior.snprintfonly copies up tosizecharacters minus the trailing null ...
And:
Another way to look at this is that the
%nwouldn't have even been encountered if it only processed up to 2 characters, so it's conceivable to expectwrittento have an invalid value...
And:
... the whole string is processed via
printf()rules, then the max-length is applied ...
Can it be verified be the standard, a standard-draft or some official source?
written is 5 because that's how many characters would be written at the point the %n is encountered. This is correct behavior. snprintf only copies up to size characters minus the trailing null (so in your case 3-1 == 2. You have to separate the string formatting behavior from the only-write-so-many characters.
Another way to look at this is that the %n wouldn't have even been encountered if it only processed up to 2 characters, so it's conceivable to expect written to have an invalid value. That's where there would be a bug, if you were expecting something valid in written at the point %n was encountered (and there wasn't).
So remember, the whole string is processed via printf() rules, then the max-length is applied.
It is not a bug: ISOC99 says
The snprintf function is equivalent to fprintf [...] output characters beyond the n-1st are discarded rather than being written to the array [...]
So it just discards trailing output but otherwise behaves the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With