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:
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 tosize
characters minus the trailing null ...
And:
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 expectwritten
to 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