printf by given pointer and format string. Issue with floats
As I want to keep track of some variables in order to see how they change, I want to create a function, which receives a format string, depending on the variable's type and a pointer to the value. I hope, that with the help of the format string, printf will properly determine the value. Actually it works, but with one exception - the float values do not print properly.
This is my code:
#include <stdio.h>
void pprint (char* fmtstr, void* p)
{
printf(fmtstr,*(long double *)p);
}
int main (int argc, char **argv)
{
char cval = 64;
int ival = -534;
unsigned int iuval = 535;
float fval = 534.64;
double dval = 53432.1;
long double ldval = 534321234.134567;
long long lval = -654321;
unsigned long long luval = 7654321;
pprint ("char: %hhdn",&cval);
pprint ("int: %dn",&ival);
pprint ("uint: %un",&iuval);
pprint ("float: %fn",&fval);
pprint ("double: %fn",&dval);
pprint ("long double: %Lfn",&ldval);
pprint ("llong: %lldn",&lval);
pprint ("ullong: %llun",&luval);
return 0;
}
And the results are:
char: 64
int: -534
uint: 535
float: 0.000000
double: 53432.100000
long double: 534321234.134567
llong: -654321
ullong: 7654321
As we can see, everything is printed OK, except the float. However, after some modification of the pprint function (casting the void pointer to float):
printf(fmtstr,*(float*)p);
The results are:
char: 0
int: 1073741824
uint: 0
float: 534.640015
double: 0.000000
long double: 0.000000
llong: -351285912010752
ullong: 4038940431088615424
Now only the float value is printed properly. Another side effect is, that casting to any other type results in successful printf of types with lower or same size. (If I cast to int, it will print properly chars, but not longs). So, casting to long double solves this problem, as it hs the largest size.
However, the problem with float remains. In order to print the float value, I need to cast the pointer to float, but nothing else. And the opposite: when I cast to float, everything except float fails. Isn't the dereference related to reading the data, located on the pointed address and passing it to printf? (the same pointer, casted to any type holds the same address?) Then, the format string is able to "read" the given bytes in the proper format - char, int, unsigned int, etc.
I have heard, that float values in variadic functions are converted to doubles. Is that relaated to the problem? Also, in some cases I'm unable to provide the value as double - because for example many of the variables, used in Opengl are floats (GLfloat).
In summary, I have 2 questions.
Why floats behave different from all another types.
Can the use of this function lead to side effects? I mean, that when printing for example an int, printf receives 12 bytes (sizeof(long double)) as second parameter, but reads only 4 ("%d" format string). From these 12 bytes the first 4 belong to the int value, that I want to print, and the next 8 are junk, which are never read by printf. Is this a problem?
Thank you.
The floats behave differently because the format specificer is expecting a 32bit sized type and you're sending it a 64 bit sized type. For the other types, you got lucky with endianness.
Listing the side affects of using a library function incorrectly is moot.
Fix the code. I'd look at the vprintf()
and vsprintf()
functions, or better yet, state your design purposes, there might be a simpler, more viable solution than the code you've shown.
这不会回答你的任何问题,但是如果你想要打印printf,你可能想看看vprintf。
You're lucky (or unlucky) it printed what you expected for so many of those types.
The C standard says, in §7.19.6.1/9
If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
In particular, many implementations use different CPU registers to pass floats and integers to printf(), and even though an integer is written in the source code, "%f" makes printf() access a floating-point register, or vice versa.
As an example, on my system, the output of your programs is
char: -1
int: 164124920
uint: 164124916
float: 0.000000
double: 0.000000
long double: 534321234.134567
llong: 140733357512904
ullong: 140733357512896
and
char: -17
int: 1200847080
uint: 1200847076
float: 534.640015
double: 0.000000
long double: 0.000000
llong: 140734394235064
ullong: 140734394235056
链接地址: http://www.djcxy.com/p/90296.html
上一篇: 如何确定浮动范围