1

I am looking an example code for invert sqrt used in quake.

I see a variable of type float: float x = 16;

and then an int variable takes the value of this expression: int i = *(int*)&a;

The way I understand it(from right to left) is that it takes the address of the variable a, typecasts it in to an integer pointer and then takes the value of that pointer and assigns it to i.

when I output the variable i in the console it's a big integer value. can someone explain more in dept of what is going on here please ?

because I expected the variable i to be 16.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
Shago
  • 101
  • 3
  • 9
  • 1
    This code demonstrates undefined behaviour due to strict aliasing rule violation, and this is probably the only thing you need to know about it. – SergeyA Mar 23 '16 at 18:31

1 Answers1

12

&a takes the address of a, a float; (int *) keeps the same address but tells the compiler now to pretend that an int is stored there; int i = * then loads the int from that address.

So you get* an integer with the same bit pattern as the float had. Floats and ints have very different encodings so you end up with a very different value.

The float is likely to be formulated like this but it's not required; your architecture may do something else. Possibly the author is doing a platform-specific optimised version of frexp.

int i = (int)x; would simply convert the float to an int, giving you 16.

Tommy
  • 99,986
  • 12
  • 185
  • 204
  • 1
    I've edited to suggest it's probably an optimised attempt to pull out the mantissa and/or exponent. Float to int conversions are expensive (you know, in relative terms) but supposing you knew that your value was always in the range 0 to 1, i.e. you already know the exponent, you might want to just grab the mantissa directly as bits to formulate your int. Classic example is on-CPU image manipulation: if all your colours start as numbers in [0.0, 1.0) then usually your output is also [0.0, 1.0) but you need to send integer bytes off to the graphics card. – Tommy Mar 23 '16 at 18:10
  • 2
    The one thing you didn't mention is that code is undefined behaviour due to violation of strict aliasing rule. – SergeyA Mar 23 '16 at 18:30
  • @SergeyA indeed, and I don't feel fully qualified to make a suitable edit. From C99, 6.2.7 defines compatible types so as not to include int and float, and 6.5.16 enforces the need for compatible pointed-to types in pointer assignment, but only with an assignment operator in the mix. I'm having difficulty finding the final link to show that the same rules apply when there's no temporary assignment in the middle. So I've marked as community wiki. Please dive in. – Tommy Mar 23 '16 at 18:55
  • 1
    first things first. The tag is C++, so C99 does not apply. C++ doesn't have a concept of *compatible type*, and 3.10 / 10 applies. – SergeyA Mar 23 '16 at 19:02