Sivachandran
Sivachandran

Reputation: 827

Ampersand inside casting

I come across this code

int n1 = 10;
int n2 = (int &)n1;

I don't understand the meaning of this casting, n2 is not reference since modifying n1 doesn't reflect n1. Strangely this code throws compiler error in gcc where as compiles fine in VC++.

Anybody know the meaning of this casting?

Upvotes: 6

Views: 1663

Answers (6)

Stack Overflow is garbage
Stack Overflow is garbage

Reputation: 248199

It does the obvious thing. Cast n1 to an int reference, and then assign it to the int n2.

And assuming n1 is an int, it should compile just fine.

It won't compile if n1 is a rvalue. The following won't compile, for example:

(int&)foo();
(int&)42;
(int&) (x+y); // assuming x and y are int variables

Upvotes: 1

AnT stands with Russia
AnT stands with Russia

Reputation: 320679

Assuming n2 is of some built-in type, the cast to int & type performs the reinterpretation of lvalue n1 (whatever type it had) as an lvalue of type int.

In the context of int n2 = (int &) n1 declaration, if n1 is by itself an lvalue of type int, the cast is superfluous, it changes absolutely nothing. If n1 is an lvalue of type const int, then the cast simply casts away the constness, which is also superfluous in the above context. If n1 is an lvalue of some other type, the cast simply reinterprets memory occupied by n1 as an object of type int (this is called type punning). If n1 is not an lvalue the code is ill-formed.

So, in the code like int n2 = (int&) n1 the cast to int & is only non-redundant (has some actual effect) when it does type punning, i.e when n1 is an lvalue of some other type (not int). For example

float n1 = 5.0;
int n2 = (int &) n1;

which would be equivalent to

int n2 = *(int *) &n1;

and to

int n2 = *reinterpret_cast<int *>(&n1);

Needless to say, this is a pretty bad programming practice.

This is, BTW, one of the cases when using a dedicated C++-style cast is strongly preferred. If the author of the code used reinterpret_cast instead of C-style cast, you probably wouldn't have to ask this question.

Of course, if n1 itself is of type int, there's no meaningful explanation for this cast. In that case it is, again, completely superfluous.

P.S. There's also a possibility that n2 is a class with overloaded conversion operator to int & type, which is a different story entirely... Anyway, you have to tell what n2 is when you ask questions like that.

Upvotes: 10

rui
rui

Reputation: 11284

I believe it's probably a typo in the original code.

GCC is usually more pedantic than VC++. However this code seems fine even though it's doing unnecessary things. Basically a temp reference is created for n1 and then the copy constructor is used to instantiate n2.

Upvotes: 1

codaddict
codaddict

Reputation: 455350

int main()
{
        int n1 = 10;
        int n2 = (int &)n1;
        cout<<n2<<endl;
}

Prints 10 as expected.
There is no problem with the cast.
It just creates a temporary reference as suggested by the next output:

int main()
{
        int n1 = 10;
        int n2 = (int &)n1;
        n2 = 20;
        cout<<n1<<endl; // print 10 and not 20.
}

Upvotes: 2

Andreas Bonini
Andreas Bonini

Reputation: 44812

It compiles in gcc too (I tried just to be sure). It simply casts n1 to a reference.

Upvotes: 0

anon
anon

Reputation:

This is perfectly valid C++ code, and does compile with g++ 4.4.1. It creates a temporary reference to n1 and then uses the value referred to by that reference to initialise n2.

This may be easier to see if expresed as a function:

void f( int & n1 ) {
   int n2 = n1;   // initialise with valuue referred to by n1
}

Note this is not valid C code, as C does not support references.

Upvotes: 11

Related Questions