4

What is the difference between

int i = 123;
int k;
k = *(int *) &i;
cout << k << endl; //Output: 123

And

int i = 123;
int k;
k = i;
cout << k << endl; //Output: 123

Both of them give same output but is there any difference?

(I found first snippet in the Quake3 code of Fast Inverse Square Root)

leemes
  • 44,967
  • 21
  • 135
  • 183
  • Are you sure that's equivalent to the snippet of code that you saw? Most likely it involved casting a pointer of one type to a different type. – jamesdlin May 20 '13 at 08:17
  • 4
    In the fast inverse sqrt snippet, like in any other instance of this (excluding cargo cult -- it's depressing that this has to be added) the types of `i` and `k` are different. –  May 20 '13 at 08:17
  • 1
    I bet the first snippet is not like that, but `float i = 1.23;` or something like that, in which case it's a "type punning cast" - converting one type to another. In C++ it would be better to use `reinterpret_cast`. – Mats Petersson May 20 '13 at 08:17
  • If you check the code closer, you will see that the `i` in the q3 algorithm is of type `long` but it's casted to a `float`, so it's not quite the same. – Some programmer dude May 20 '13 at 08:18
  • Note that I removed the `C` tag, because this code is C++. Type casting in C behaves differently than in C++. – leemes May 20 '13 at 08:20
  • So *(int *) &i; this is a hack that allowes using reinterpret casting in C ? –  May 20 '13 at 08:48

3 Answers3

6

In the Q3:

float Q_rsqrt( float number )
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = number * 0.5F;
    y  = number;
    i  = * ( long * ) &y;                       // evil floating point bit level hacking
    i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
    y  = * ( float * ) &i;
    y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
//  y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed

    return y;
}

As I understand, you are interested in the following line:

    i  = * ( long * ) &y;

The y is a float, and the i is an long. Thus it is the reinterpretation of the floating point bit pattern as integer bit pattern.

Alex
  • 9,891
  • 11
  • 53
  • 87
  • The algorithm of the code seems to be [Fast inverse square root](http://en.wikipedia.org/wiki/Fast_inverse_square_root) – SKi May 20 '13 at 08:27
  • @User1 in Wiki it is mentioned that it is taken from Q3 source. – Alex May 20 '13 at 08:28
  • Indeed. There is also nice explanation why there are those strange castings and magic numbers in the code. – SKi May 20 '13 at 08:33
  • @User1 As far as I understood, the OP asked exactly about this part. – Alex May 20 '13 at 08:35
  • So why the author of this code did write i = * (long *) &y; instead of i = (long) y; ? –  May 20 '13 at 08:46
  • 1
    @user2400925 because if you do `i = (long) y;` you will cast `float` to `long` and will modify a bit pattern, because a value of `y` will be rounded to the least closest integer. In the case ` i = * (long *) &y`, the bit pattern stays the same. – Alex May 20 '13 at 08:56
  • So *(int *) &i; this is a hack that allowes using reinterpret casting in C ? –  May 20 '13 at 09:10
  • And same as: reinterpret_cast(&i); ? –  May 20 '13 at 09:22
  • 1
    In accordance to [this](http://stackoverflow.com/questions/573294/when-to-use-reinterpret-cast), you should either `reinterpret_cast(i)` or `*(reinterpret_cast(&i))` I am not as good in `C++`, so can be a bit wrong. – Alex May 20 '13 at 09:26
  • 1
    Type punning in C++ is done by casting references. The equivalents of the two casts in the example are `i = reinterpret_cast(y);` and `y = reinterpret_cast(i);`. (See 5.2.10 [expr.reinterpret.cast] p11). – Casey May 20 '13 at 17:36
2

It all depends whether i is an object or a primitive type. If it is an object, operator* might be overloaded, giving an different overall meaning.

davideanastasia
  • 366
  • 1
  • 13
1

No, there is no difference, both assignments are essentially copying an int's worth of bits from the memory storing i to the memory storing k.

Sometimes tricks like these are used when the types of the source and destination variables differ, but this is just plain int to int.

A sufficiently clever compiler ought to generate the exact same code for both versions, I think.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • So why the author of this code did write i = * (long *) &y; instead of i = (long) y; ? –  May 20 '13 at 08:47