Reputation: 2045
define a float variable a, convert a to float & and int &, what does this mean? After the converting , a is a reference of itself? And why the two result is different?
#include <iostream>
using namespace std;
int
main(void)
{
float a = 1.0;
cout << (float &)a <<endl;
cout << (int &)a << endl;
return 0;
}
thinkpad ~ # ./a.out
1
1065353216
Upvotes: 5
Views: 2686
Reputation: 154047
It means undefined behavior:-).
Seriously, it is a form of type punning. a
is a float
, but a
is also a block of memory (typically four bytes) with bits in it. (float&)a
means to treat that block of memory as if it were a float
(in other words, what it actually is); (int&)a
means to treat it as an int
. Formally, accessing an object (such as a
) through an lvalue expression with a type other than the actual type of the object is undefined behavior, unless the type is a character type. Practically, if the two types have the same size, I would expect the results to be a reinterpretation of the bit pattern.
In the case of a float
, the bit pattern contains bits for the sign, an exponent and a mantissa. Typically, the exponent will use some excess-n notation, and only 0.0
will have 0 as an exponent. (Some representations, including the one used on PCs, will not store the high order bit of the mantissa, since in a normalized form in base 2, it must always be 1. In such cases, the stored mantissa for 1.0
will have all bits 0.) Also typically (and I don't know of any exceptions here), the exponent will be stored in the high order bits. The result is when you "type pun" a floating point value to a an integer of the same size, the value will be fairly large, regardless of the floating point value.
Upvotes: 9
Reputation: 33467
cout << (float &)a <<endl;
cout << (int &)a << endl;
The first one treats the bits in a like it's a float. The second one treats the bits in a like it's an int. The bits for float 1.0 just happen to be the bits for integer 1065353216.
It's basically the equivalent of:
float a = 1.0;
int* b = (int*) &a;
cout << a << endl;
cout << *b << endl;
(int &) a
casts a to a reference to an integer. In other words, an integer reference to a. (Which, as I said, treats the contents of a as an integer.)
Edit: I'm looking around now to see if this is valid. I suspect that it's not. It's depends on the type being less than or equal to the actual size.
Upvotes: 15
Reputation: 9979
The values are different because interpreting a float
as an int &
(reference to int
) throws the doors wide open. a
is not an int
, so pretty much anything could actually happen when you do that. As it happens, looking at that float
like it's an int
gives you 1065353216
, but depending on the underlying machine architecture it could be 42
or an elephant in a pink tutu or even crash.
Note that this is not the same as casting to an int
, which understands how to convert from float
to int
. Casting to int &
just looks at bits in memory without understanding what the original meaning is.
Upvotes: 2