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: %hhd\n",&cval);
pprint ("int: %d\n",&ival);
pprint ("uint: %u\n",&iuval);
pprint ("float: %f\n",&fval);
pprint ("double: %f\n",&dval);
pprint ("long double: %Lf\n",&ldval);
pprint ("llong: %lld\n",&lval);
pprint ("ullong: %llu\n",&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.