Why C memory field reinterpreting through cast differs between regular cast and cast through pointer?

Viewed 63

I wrote such code example:

int main(void) {
     double f = 0.1;
     int i, j;

     i = *(int *)(&f);
     j = (int)f;
     printf("%d\n%d\n", i, j); 

     return 0;
}

And I expected that the results will be the same. Because I thought that generally these are the same things: to reinterpret data of one type as data of another type and take a pointer of one type, cast it to pointer of another type and then access the data. But I got:

-1717986918
0

What is the reason? Sorry, if obvious.

2 Answers
j = (int)f;

this gets the value of f and somehow converts it into a integer value.

i = *(int *)(&f);

this the address of f and tells the compiler "this is an integer", then stores its value into i.

The second form works with raw bits, without taking into acount that a double has different representation in memory than an integer.

EDIT

As Christian Gibbons pointed out, this sort of accessing an object through a pointer of different type is undefined behavior, which means that your app may do all kind of unexpect things, even running well ;)

Just complementing @Ripi2 answer.

The first case performs a conversion and thus the binary representation is different. For instance, the number 3.141516 has bits representing the 3 and some bits representing the .141516. When you cast to an int the compiler simply discards the bits for the fractional part and uses the remaining bits as the lowest significative bits of an integer. Thus you get a "3".

For user-defined types, you can actually implement your own conversion operators. All you have to do is creating an operator SomeType() const method in your class. For instance, if your class has an operator int() const method, then it will be used when you cast on object of your class to an int (including when you pass your object to a function that expects an int). Of course, the language already includes valid conversions for plain old data, such as from a floating-point to an integer.

On the other hand, if you cast a pointer from one type to another the compiler will not perform any conversion. When you deference the pointer it will just treat the bits located at that location as the binary representation of the type you asked and show you the result, which could be anything if you cast it to something it is not. This is similar to the dangers of using reinterpret_cast without knowing what you are doing.

Related