When converting a double to a string, what can the first string character be?
Easy to generate "0123456789-+ iInN"
. But other char
are possible, depending on how far we want to stretch it.
Obviously, it could be one of the following: 0-9
, -
, .
but since we are using floating point math here, there are probably more characters that could end up in buf[0] like I
for Inf
or N
for NaN
and maybe even more?
snprintf(buf, n, "%.14g", d);
When n = 1
, expect buf[0] == '\0'
When n = 0
, expect buf[0]
to be unchanged so any char
value is possible there.
With "%.14g"
I would not expect 'I'
nor 'N'
, but 'i'
and 'n'
.
"%.14G"
would produce 'I'
and 'N'
.
A leading '.'
does not happen with this format.
With other locales, (research setlocale()
), the '-'
may be something else. I know of no locale that does that though.
Other formats
With other format "% something [gefaGefa]"
strings:
The first character could be a space ' '
or '+'
. Like '-'
, that can vary with locale.
If a leading '.'
is possible (I am confident this is not possible with standard formats), others locales may use an alternate such as ','
.
With implementation specific formats, any lead character is possible.
With invalid formats, any lead character is possible due to undefined behavior.
#include <stdio.h>
int main(void) {
char s[1000];
double inf = strtod("inf", 0);
double nan = strtod("nan", 0);
snprintf(s, sizeof s, "%g\n", 0.0); printf("%3d %.1s\n", s[0], s);
snprintf(s, sizeof s, "%g\n", 9.0); printf("%3d %.1s\n", s[0], s);
snprintf(s, sizeof s, "%g\n", -1.0); printf("%3d %.1s\n", s[0], s);
snprintf(s, sizeof s, "%+g\n", +1.0); printf("%3d %.1s\n", s[0], s);
snprintf(s, sizeof s, "%g\n", inf); printf("%3d %.1s\n", s[0], s);
snprintf(s, sizeof s, "%G\n", inf); printf("%3d %.1s\n", s[0], s);
snprintf(s, sizeof s, "%g\n", nan); printf("%3d %.1s\n", s[0], s);
snprintf(s, sizeof s, "%G\n", nan); printf("%3d %.1s\n", s[0], s);
snprintf(s, sizeof s, "%5g\n", 1.0); printf("%3d %.1s\n", s[0], s);
snprintf(s, 1, "%g\n", 1.0); printf("%3d %.1s\n", s[0], s);
s[0] = 'z';
snprintf(s, 0, "%g\n", 1.0); printf("%3d %.1s\n", s[0], s);
return 0;
}
Output
48 0
57 9
45 -
43 +
105 i
73 I
110 n
78 N
32
0
122 z
Is the behaviour of snprintf standardized in this situation across different compilers and platforms?
Yes. Compliant possibilities include "0123456789-+ iInN"
. Some compilers may add additional implementation defined ones.
where is the specification (?)
Look for the C spec. Latest is C17
Where do I find the current C or C++ standard documents?
Details:
infinity --> [-]inf or [-]infinity (efga) or uppercase version (EFGA)
nan --> [-]nan or [-]nan(n-char-sequence) or uppercase prefix version
%f --> [−]ddd.ddd,if a decimal-point character appears,at least one digit appears before it.
%F --> like %f
%e --> [−]d.ddd e±dd
%e --> like %e, but with E
%g --> converted in style f or e
%G --> converted in style F or E
%a --> [−]0xh.hhhh p±d
%A --> like %a, but with X,P