What float value makes sprintf_s() produce "1.#QO"?
I have some (legacy embedded c) code which produces a .csv file by means of some sprintf
calls. Occasionally I see values of 1.#QO
. I've tried reproducing those values with conditions which should give negative infinity, positive infinity and NaN but none of them appear to give me the magical 1.#QO
result. So what is it that produces that value?
...and yes, I know there's obviously something going wrong in the maths which produce that value, but understanding what it means would assist in the debugging effort.
[Edit 1] The actual line which does the conversion is:
sprintf_s(txt, CSV_HEADER_SIZE, "%.3f", value);
where:
#define CSV_HEADER_SIZE (100)
char txt[CSV_HEADER_SIZE];
I'm compiling with MS Visual Studio 2008.
[Edit 2] A bit more digging shows 0xFFFFFFFF
gives -1.#QO
:
unsigned int i = 0xFFFFFFFF;
float* f = (float*)&i;
printf("%.3f", *f); // gives -1.#QO
..and looking at that in the Visual Studio debugge开发者_运维技巧r expands it to -1.#QNAN00
so it looks like this is probably a Microsoft-specific representation of NaN
?
"-1.#QO" is "-1.#QNAN" after "rounding" for 3 places after the decimal. The N rounds to an O as 'A' >= '5' and 'N' + 1 == 'O'.
This is similarly why your debugger shows "-1.#QNAN00", as it prints with 7 places and adds padding zeros to the end.
QNaN is quiet NaN.
After a lot of fiddling around I can conclusively say that setting a 4-byte float to 0x7FFFFFFF
and passing it into sprintf_s
with a format specifier of %.3f
is what gave me 1.#QO
:
const int bufSize = 100;
char buf[bufSize];
unsigned int i;
float* f = (float*)&i;
int retval;
i = 0xFFFFFFFF;
retval = sprintf_s(buf, bufSize, "%.3f\n", *f);
printf("sprintf_s returned %d, converted val = %s", retval, buf); // == sprintf_s returned 7, converted val = -1.#QO
retval = sprintf_s(buf, bufSize, "%f\n", *f);
printf("sprintf_s returned %d, converted val = %s", retval, buf); // == sprintf_s returned 10, converted val = -1.#QNAN0
i = 0x7FFFFFFF;
retval = sprintf_s(buf, bufSize, "%.3f\n", *f);
printf("sprintf_s returned %d, converted val = %s", retval, buf); // == sprintf_s returned 6, converted val = 1.#QO
retval = sprintf_s(buf, bufSize, "%f\n", *f);
printf("sprintf_s returned %d, converted val = %s", retval, buf); // == sprintf_s returned 9, converted val = 1.#QNAN0
...it seems that the %.3f
format specifier was cropping the NAN result so what should have been 1.#QNAN0
was being chopped down to 1.#QO
.
A little googling points to a divide by 0 error. Though I would expect something different if that were the case. That said, it appears to be specific to MS/Visual C.
Did you check whether sprintf_s() returned a failure? If it does, you should not use the result. Since the code doesn't look like you checked, I think you should do that checking. In fact, if you don't test the result from one of the *_s()
functions, you are headed for trouble.
精彩评论