In below simple c test program two printf statements return different values. ( check last four printf statements).
int main () { char c, *cc; int i; long l; float f; c = 'Z'; i = 15; l = 7777; f = 9999999312; cc = &c; printf("nc = %c, cc= %u", *cc, cc); cc = &i; printf("nc = %d, cc= %u", *cc, cc); cc = &l; printf("nc = %ld, cc= %u", *( long* )cc, cc); printf("nc = %ld, cc= %u", *cc, cc); cc = &f; printf("nc = %f, cc= %u", *(float *)cc, cc); printf("n cc= %u", cc); printf("nc = %f, cc= %u", *cc, cc); printf("nc = %f, cc= %u", *(float *)cc, cc); printf("nc = %f, cc using pointer = %p", *(float *)cc, cc); printf("nc = %f, cc using pointer =%p", *cc, cc); return 0; }
output : –
c = Z, cc= 755585903 c = 15, cc= 755585904 c = 7777, cc= 755585912 c = 97, cc= 755585912 c = 9999998976.000000, cc= 755585908 cc= 755585908 c = 9999998976.000000, cc= 4294967288 c = 9999998976.000000, cc= 755585908 c = 9999998976.000000, cc using pointer = 0x7ffc37f4ace4 c = 9999998976.000000, cc using pointer =0xfffffff8
I am running it in eclipse ide and using Ubuntu Linux.
Why does it behave differently?
Advertisement
Answer
In several places you are using the wrong format specifier to printf
. In particular, on this line:
printf("nc = %f, cc= %u", *cc, cc);
The first parameter has type char
, but you use %f
which expects a double
. Also, the second parameter has type char *
but %u
is expecting an unsigned int
. Using the wrong format specifiers invokes undefined behavior.
That being said, here is what is most likely happening under the hood:
On most hosted implementations, floating point numbers are not pushed onto the stack the way integer types and pointers are, but are instead stored in a floating point register.
When you run the above printf
command, both *cc
and cc
are pushed onto the stack because neither of them are floating point numbers. When printf
then looks for the first parameter it sees %f
, so it retrieves a value from a floating point register. Since you did actually pass a floating point value the prior time you called printf
that value is still there, and that value happens to be the value you actually wanted to print, so that’s what gets printed.
Then when printf
goes to print the next parameter, it sees %u
in the format so the value is pulled from the stack. That value is *cc
, which points to the first byte in the representation of f
.
Assuming a float
is a IEEE754 single precision floating point number, the value it contains is represented as 0xf8021550
. The first byte of that is 0xf8
. Since cc
points to a char
, which in your case appears to be signed, it is interpreted as a negative value. When passed to printf
the value is promoted to type int
, so the actual value passed in is 0xfffffff8
, which is what you see being printed.
To reiterate however, the output you’re seeing is undefined behavior. The output could change if you build it on a different machine, use a different compiler, or just use a different optimization setting.