4

Given the following snippet of code:

int *iptr;
float *fptr;
float fval;
fval = 0.0;
fptr = &fval;
iptr = fptr;
printf("%d \n", *iptr);
fval = 1.0;
printf("%d \n", *iptr);

The output is:

0
1065353216

Why does the first print statement at least approximately match the value associated with *iptr (0.0), yet the second print statement doesn't?

Shmil The Cat
  • 4,548
  • 2
  • 28
  • 37
David Smith
  • 187
  • 3

6 Answers6

12

When you write printf("%d \n", *iptr);, you are asking printf to interpret the value pointed to by iptr as an integer.

It just so happens that float version of 0 is represented by the same bits of the int version of 0. In particular, the bits are all 0.

However, an arbitrary float, such as 1.0 will have a different bit representation (as defined by IEEE Standards) which will make little sense when interpreted as an int.

This Wikipedia article explains how a float is represented as bits.

ajay
  • 9,402
  • 8
  • 44
  • 71
merlin2011
  • 71,677
  • 44
  • 195
  • 329
  • @merlin2011: is strict aliasing not an issue here? (e.g., here: http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule, "So basically if you have an int* and a float* they are not allowed to point to the same memory location. If your code does not respect this, then the compiler's optimizer will most likely break your code." –  Apr 11 '14 at 08:51
  • @dmcr_code It definitely is. That's why I added my own answer. – ajay Apr 11 '14 at 08:58
  • 1
    @ajay: Yes, I think it has to be mentioned; (unfortunately) C has many "nasty" details which one needs to know(I myself got acquainted with some of them recently, like this one, or signed/unsigned mixing, etc.) –  Apr 11 '14 at 09:02
  • @dmcr_code Writing safe, standards compliant C code is far from a trivial task and requires serious effort. I myself am learning it the hard way. – ajay Apr 11 '14 at 09:11
  • @ajay: standards compliance is smth I haven't "considered" so far, I usually try to write with what I have learned (e.g., using books), and not reinvent the wheel and try to avoid some cryptic expressions, etc. and watch for pitfalls like this one for example –  Apr 11 '14 at 09:19
  • @ajay, Thanks for supplementing this answer with your own. Strict aliasing is certainly an issue, but that was not the first thing that came to mind when I saw this question. :) – merlin2011 Apr 11 '14 at 16:57
3

The statement iptr = fptr; will invoke undefined behaviour.

There is not much point in speculating about the outcome therefore.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
3

@merlin has explained the output of your code very nicely and clearly. However, there's more to it so I will add it here. Your code violates the strict aliasing rule and invokes undefined behaviour. Strict aliasing rule means different pointer types should not point to the same memory location.

iptr = fptr;

iptr is of type int * and fptr is of type float *. This statement assigns fptr to iptr - a different type - which means both now point to fval. This breaks the strict aliasing rule. This causes undefined behaviour which means unpredictable behaviour. The standard imposes no requirements on the implementation to deal which such cases. In short, you should avoid code which causes undefined behaviour.

Community
  • 1
  • 1
ajay
  • 9,402
  • 8
  • 44
  • 71
2

Its an undefined behavior: iptr = fptr;. You cannot print a float as an int, floats are stored in IEEE754 format

You need to try this:

printf("%d", fval);
Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331
1

A zero floating point number consists of zeroes. Any other number is not just the number but an exponent and a mantissa - of course neither of them is just your number.

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
1

Floats are stored in IEEE754 format, in which the value of a number such as 1.0 is quite different to 1 (it is offset to allow for negative numbers and exponents). You cannot print a float as an int and have the result resemble the number assigned to the float.

ntremble
  • 71
  • 4