What's the meaning of (int&) conversion in C++

float b = 1.0f;
int i = (int)b;
int& j = (int&)b;

cout << i << endl;
cout << j << end;

Then the output of i was 1, and the output of j was 1065353216! It is a big surprise to me! So what is the true meaning of (int&) conversion?

7 c++
13.10.2009 16:09:14
6 ОТВЕТОВ
РЕШЕНИЕ

This is the problem with a C-style cast. You have to look closely to see what you're getting. In your case "(int)" was a normal static cast. The value is converted to an int via truncation. In your case "(int&)" was a reinterpret cast. The result is an lvalue that refers to the memory location of b but is treated as an int. It's actually a violation of the strict aliasing rules. So, don't be surprized if your code won't work anymore after turning on all optimizations.

Equivalent code with C++ style casts:

float b = 1.0f;
int i = static_cast<int>(b);
int& j = reinterpret_cast<int&>(b);
cout<<i<<endl;
cout<<j<<end;

Check your favorite C++ book on these kinds of casts.

19
13.10.2009 16:13:12
Yes, It's a great answer. But I get one more question. Why an error, "error: invalid static_cast from type ‘float’ to type ‘int&’", happened when I used static_cast to cast a float to int& like "float b = 1.0f; int &j = static_cast<int&> b; ". I didn't find the limitations of static_cast in my favoraite C++ book, "The C++ Programming Language".
toby 14.10.2009 02:22:10
That's the protection you get from using C++ style casts. If the compiler accepts a static_cast chances are you're not doing anything wrong. The only unsafe things a static cast lets you do is an unchecked conversion from Base*/Base& to Derived*/Derived& and void* to T* as far as I can remember. It basically can invert implicit conversions, not more -- not counting const conversions.
sellibitze 14.10.2009 06:44:15

Seems like you are trying to create an int reference to a float by using (int&) cast. That will not work since floats are represented differently than int. This will not work.

If the representation of float and int are same then it might have worked.

1
13.10.2009 16:23:27
float b = 1.0f;
...
int& j = (int&)b;

In the second conversion, you're looking at the memory space that contains b as if it was a memory space that contains an int. Floating point values are stored in a manner that's completely different as integers, so the results are really different...

2
13.10.2009 16:23:54

In hexadecimal 1065353216 is 0x3F800000. If you interpret that as a 32-bit floating point number you get 1.0. If you write it out in binary you get this:

3    F    8    0    0    0    0    0
0011 1111 1000 0000 0000 0000 0000 0000

Or grouped differently:

0 01111111 00000000000000000000000
s eeeeeeee vvvvvvvvvvvvvvvvvvvvvvv

The first bit (s) is the sign bit, the next 8 bits (e) are the exponent, and the last 23 bits (v) are the significand. "The single precision binary floating-point exponent is encoded using an offset binary representation, with the zero offset being 127; also known as exponent bias in the IEEE 754 standard." Interpreting this you see that the sign is 0 (positive), the exponent is 0 (01111111b = 127, the "zero offset"), and the significand is 0. This gives you +00 which is 1.0.

Anyhow, what's happening is that you are taking a reference to a float (b) and reinterpreting it as an int reference (int&). So when you read the value of j you get the bits from b. Interpreted as a float those bits mean 1.0, but interpreted as an int those bits mean 1065353216.

For what it's worth, I have never used a cast using & like (int&). I would not expect to see this or use this in any normal C++ code.

11
13.10.2009 16:42:40
Hey, there is a typo here, (v) is repeated twice, fix the first (v) to (e).
legends2k 13.10.2009 16:30:57
I read the assembly code generated by g++. This is the exactly happening in the program.
toby 14.10.2009 02:28:33

In this particular case the conversion in question has no meaning. It is an attempt to reinterpret memory occupied by a float object and an int Lvalue. This is explicitly illegal in C/C++, meaning that it produces undefined behavior. Undefined behavior - that's the only meaning that it has in this case.

2
24.07.2012 18:50:32

What were you going to do? The same thing:

float b = 1.0f;
int i = (int) b;
int* j = (int*)b;//here we treat b as a pointer to an integer
cout<<i<<endl;
cout<<(*j)<<endl;

How to fix:

float b = 1.0f;
int i = (int) b;
int castedB = (int)b;//static_cast<int>(b);
int& j = castedB;
cout<<i<<endl;
cout<<j<<endl;
1
13.10.2009 19:57:37