7

The reinterpret_cast as we know can cast any pointer type to any another pointer type. The question I want to ask regarding this cast operator are:

  1. How does reinterpret_cast work, What is the magic(the internal implementation) that allows reinterpret_cast to work?
  2. How to ensure safety when using reinterpret_cast? As far as i know, it doesn't guarantee of safe casting, So what precaution to take while using reinterpret_cast?
  3. What is the practical usage of this operator. I have not really encountered it in my professional programing experience, wherein I could'nt get around without using this operator.Any practical examples apart from usual int* to char* will be highly helpful and appreciated.

One other Question regarding casting operators in general:
Casting operators(static_cast, dynamic_cast, const_cast, reinterpret_cast) are all called Operators i.e is to the best of my understanding, So is it correct statement to make that casting operators cannot be overloaded unlike most other operators (I am aware not all operators can be overloaded and I am aware of which can't be(except the Q I am asking, Please refrain flaming me on that) Just I had this doubt that since they are operators, what does the standard say about these?

Josh Lee
  • 171,072
  • 38
  • 269
  • 275
Alok Save
  • 202,538
  • 53
  • 430
  • 533

9 Answers9

5
  1. There is no magic. reinterpret_cast normally just means (at least try to) treat what you find at this address as if it was the type I've specified. The standard defines little enough about what it does that it could be different from that, but it rarely (if ever) really is.
  2. In a few cases, you can get safety from something like a discriminated union. For example, if you're reading network packets, and read enough to see that what you've received is a TCP packet, then you can (fairly) safely do a reinterpret_cast from IPHdr to TCPHdr (or whatever names you happen to have used). The compiler won't (again, normally) do much though -- any safety is up to you to implement and enforce.
  3. I've used code like I describe in 2), dealing with different types of network packets.

For your final question: you can overload casting for a class:

class XXX { 
public:
    operator YYY() { return whatever; }
};

This can be used for conversions in general though -- whether done by a static_cast, C-style cast, or even an implicit conversion. C++0x allows you to add an explicit qualifier so it won't be used for implicit conversions, but there's still no way to differentiate between a static_cast and a C-style cast though.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 2
    I don't get the last sentence: '*there is not way to differentiate between a static_cast and a C-style cast*'. The thing is that C-style casts can be either `static_cast` or `reinterpret_cast` (possibly including `const_cast` with either of them). In all cases where a `static_cast` is valid, the C-style cast will perform an `static_cast` while when it is not possible it will do a `reinterpret_cast`. If const-ness (or volatile-ness) is been modified then it will include a `const_cast` in the process. – David Rodríguez - dribeas Nov 05 '10 at 16:54
  • @dribeas: I just meant that when you define such a conversion operator, it can be invoked via either a C-style case or a static_cast in the client code, and you can't (for example) provide one overload for how a static_cast will be done, and a different one for how a C-style cast will be done. – Jerry Coffin Nov 05 '10 at 16:57
  • In the answer to the final Q, it is called "Operator conversion" and AFAIK the "explicit" qualifier is even allowed in C++. My final Q actually meant can one overload lets say dynamic_cast operator? – Alok Save Nov 05 '10 at 17:02
  • 2
    @Als: Actually they're "conversion functions" (per §12.3.2/1), not that the difference matters. C++03 has `explicit`, but only for ctors, not for conversion functions. A conversion function is all that's available -- for anything else, the answer is "no." – Jerry Coffin Nov 05 '10 at 17:07
  • @Jeffry: Thanks, indeed C++03 supports explicit is only for constructors. Nice answer :) – Alok Save Nov 06 '10 at 04:55
2

reinterpret_cast generally lets you do some very bad things. In the case of casting a pointer it will permit casting from one type to another which has absolutely no reason to assume this should work. It's like saying "trust me I really want to do this". What exactly this does is unpredictable from one system to the next. On your system it might just copy the bit-patterns, where as on another one it could transform them in some (potentially useful) way.

e.g.

class Foo {
    int a;
};

class Bar {
    int a;
};

int main() {

  Foo a;

  // No inheritance relationship and not void* so must be reinterpret_cast 
  // if you really want to do it
  Bar *b = reinterpret_cast<Bar*>(&a);

  char buffer[sizeof(Bar)];

  Bar *c = reinterpret_cast<Bar*>(buffer); // alignment?

}

Will quite happily let you do that, no matter what the scenario. Sometimes if you're doing low-level manipulation of things this might actually be what you want to do. (Imagine char * of a buffer casting to something user defined type)

Potential pitfalls are huge, even in the simplest case like a buffer, where alignment may well be a problem.

With dlsym() on Linux it's useful to be able to cast void* to a function pointer, which is otherwise undefined behaviour in C++. (Some systems might use separate address spaces or different size pointers!). This can only be done with reinterpret_cast in C++.

Flexo
  • 87,323
  • 22
  • 191
  • 272
  • "Undefined" is technically the wrong word. The types of conversions `reinterpret_cast` can do are explicitly defined in the Standard, and the mappings are implementation-defined. – David Thornley Nov 05 '10 at 16:44
  • I thought the void*/function pointer one was undefined, but reinterpret_cast would accept. – Flexo Nov 05 '10 at 16:46
2

First, it's unclear what you mean by "non-standard pointer". I think your premise is flawed. Happily it doesn't seem to affect the questions.

"How does [it] work?" Well, the intent, as you can guess from the name, is to just change the interpretation of a bitpattern, perhaps extending or shorting as appropriate. This is a kind of change of type where the bitpattern is left unchanged but the interpretation and hence conceptual value is changed. And it's in contrast to a kind of change of type where the conceptual value is kept (e.g. int converted to double) while the bitpattern is changed as necessary to keep the conceptual value. But most cases of reinterpret_cast have implementation defined effect, so for those cases your compiler can do whatever it wants -- not necessarily keeping the bitpattern -- as long as it is documented.

"How to ensure safety" That is about knowing what your compiler does, and about avoiding reinterpret_cast. :-)

"What is the practical usage". Mostly it is about recovering type information that's been lost in C-oriented code where void* pointers are used to sort of emulate polymorphism.

Cheers & hth.,

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • 1
    Conversions from `void*` do not require `reinterpret_cast`, but rather `static_cast` (which is as bad as a `reinterpret_cast` in this particular case, but *different* none the less) – David Rodríguez - dribeas Nov 05 '10 at 16:49
  • Except that you can static_cast to/from void*, no? The problem with MS's interface is that they use integers instead of void*. Isn't the static_cast to/from void* also 'slightly' safer too since it is guaranteed to grab the beginning of the object instead of just switching type of the pointer? I guess there can be cases for both methods since casting from a void* to a subclass in an MI derivative would go badly with static_cast. Most of the time I seem to recall using static_cast though. – Edward Strange Nov 05 '10 at 16:55
  • @David: right as far as it goes. I was thinking mainly of cases like in Microsoft's [`QueryInterface`](http://msdn.microsoft.com/en-us/library/ms682521%28VS.85%29.aspx). Direct conversion from `void**` to `T**` does require `reinterpret_cast`. Cheers, – Cheers and hth. - Alf Nov 05 '10 at 16:56
  • In fact, formally in C++03 it is illegal to cast from or to `void*` to or from another pointer type (in practice, too much code does this, so no sane compiler rejects it). – Johannes Schaub - litb Nov 05 '10 at 19:02
  • @Johannes: would you mind providing a reference to that defect? – Cheers and hth. - Alf Nov 05 '10 at 19:59
  • @Alf see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1120 . C++03 did require this reinterpret_cast to fail, but at least [basic.stc.dynamic.safety]p3b4 in the C++0x draft expects such a cast to work, so I expect them to make the cast work in C++0x. – Johannes Schaub - litb Nov 05 '10 at 20:16
  • @Johannes: thanks. This almost like a joke, though... I think I'll introduce Alf's Law of Abstraction: "Premature abstraction is the root of just as much Evil". Also, "You know it's not a good abstraction when it's more complicated than the concrete thing it abstracts". Cheers, – Cheers and hth. - Alf Nov 05 '10 at 20:19
1
  1. reinterpret_cast only works on pointers. The way it works is that it leaves the value of the pointer alone and changes the assumed type information about it. It says, "I know these types are not equivalent, but I want you to just pretend this is now a pointer to T2." Of course, this can cause any number of problems if you use the T2 pointer and it does not point to a T2.

  2. There are very few guarantees about reinterpret_cast, which is why it is to be so avoided. You're really only allowed to cast from T1 to T2 and then back to T1 and know that, given some assumptions, that the final result will be the same as what you started with.

  3. The only one I can think of is casting a char* to an unsigned char*. I know that the underlying representation is the same in my implementation so I know the cast is safe. I can't use a static cast though because it's a pointer to a buffer. In reality, you'll find very little legitimate use of reinterpret_cast in the real world.

Yes, they are operators. AFAIK you can't override them.

Edward Strange
  • 40,307
  • 7
  • 73
  • 125
  • 2
    Hi Noah. Long time no see :-). Nit re (1): reinterpret_cast also works nicely on references. Nit re (2): there is also a guarantee about reinterpret_cast to/from first member of a POD struct. Re (3), not a nit: see my answer (an example is Microsoft's `QueryInterface`). Cheers, – Cheers and hth. - Alf Nov 05 '10 at 16:44
  • 1
    Yeah, if you're using MS's C and/or C++ libraries you're probably going to have to use reinterpret_cast a lot because of the use of long as the vague type instead of void*. Most other C libraries I've used though used void*. I don't know the history or reasons why MS chose long instead but you can static_cast to/from void* (though it's not really much safer). I guess I didn't realize it worked on references...never done so. And yeah, I don't know all the rules unless I have to. – Edward Strange Nov 05 '10 at 16:51
1

One "practical" use of reinterpret_cast.

I have a class where the members are not meant to be read. Example below

class ClassWithHiddenVariables
{
private:
    int a;
    double m;
public:
    void SetVariables(int s, int d)
    {
        a = s;
        m = d;
    }
}; 

This class is used in a thousand places in an application without a problem.

Now, because of some reason I want see the members in one specific part. However, I don't want to touch the existing class.So break the rules as follows.

Create another class with the same bit pattern and public visibility. Here the original class contains an int and double.

class ExposeAnotherClass
{
public:
    int a_exposed;
    double m_exposed;
};

When you want to see members of the ClassWithHiddenVariables object, use reinterpret_cast to cast to ExposeAnotherClass. Example follows

ClassWithHiddenVariables obj;
obj.SetVariables(10, 20.02);    
ExposeAnotherClass *ptrExposedClass;
ptrExposedClass = reinterpret_cast<ExposeAnotherClass*>(&obj);  
cout<<ptrExposedClass->a_exposed<<"\n"<<ptrExposedClass->m_exposed;

I don't think this situation ever occurs in real world. But this is just an explanation of reinterpret_cast which considers objects as bit patterns.

Jimmy
  • 3,224
  • 5
  • 29
  • 47
  • @Als, thanks. If we think more about it, we can see reinterpret_cast should be there in C++ for "completeness". – Jimmy Nov 06 '10 at 13:54
0

reinterpret_cast tells the compiler "shut up, it's a variable of type T*" and there's no safety unless it is really a variable of type T*. On most implementations just nothing is done - the same value in the variable is passed to the destination.

Your class can have conversion operators to any type T* and those conversions will either be invokde implicitly under certain conditions or you can invoke them explicitly using static_cast.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 2
    Even if it IS really a variable of type T* it can behave erroneously. For if you have struct X : Y,Z {} and you cast an X* to a Z* using reinterpret_cast and then use that pointer you're probably going to get bad results and you WILL get undefined behavior. Although X* is not a Z* in a very correct and standardesque view, it could cause misunderstanding because many are going to consider that because X is-a Z that X* is-a Z*. – Edward Strange Nov 05 '10 at 16:45
0

I've used reinterpret_cast a lot in Windows programming. Message handling uses WPARAM and LPARAM parameters that need casting to the correct types.

DanDan
  • 10,462
  • 8
  • 53
  • 69
-1

The reinterpret_cast as we know can cast any non-standard pointer to another non-standard pointer.

Almost, but not exactly. For example, you can't use reinterpret_cast to cast a const int* to an int*. For that, you need const_cast.

How does reinterpret_cast work, What is the magic(the internal implementation) that allows reinterpret_cast to work?

There's no magic at all. Ultimately, all data is just bytes. The C++ type system is merely an abstraction layer which tells the compiler how to "interpret" each byte. A reinterpret_cast is similar to a plain C-cast, in that it simply says "to hell with the type system: interpret these bytes as type X instead of type Y!"

How to ensure safety when using reinterpret_cast? As far as i know, it doesn't guarantee of safe casting, So what precaution to take while using reinterpret_cast?

Well, reinterpret_cast is inherently dangerous. You shouldn't use it unless you really know what you're doing. Try to use static_cast instead. The C++ type system will protect you from doing anything too dangerous if you use static_cast.

What is the practical usage of this operator. I have not really encountered it in my professional programing experience, wherein I could'nt get around without using this operator.Any practical examples apart from usual int* to char* will be highly helpful and appreciated.

It has many uses, but usually these uses are somewhat "advanced". For example, if you are creating a memory pool of linked blocks, and storing pointers to free blocks on the blocks themselves, you'll need to reinterpret_cast a block from a T* to a T** to interpret the block as a pointer to the next block, rather than a block itself.

Charles Salvia
  • 52,325
  • 13
  • 128
  • 140
  • 1
    You're second paragraph is wrong. `reinterpret_cast` may or may not change the representation (Standard 5.2.10/3), and the mapping is purely implementation-defined. Consider C casting of `int` to `double` compared to casting of `int *` to `int`. – David Thornley Nov 05 '10 at 16:41
  • 2
    Nope. A reinterpret_cast is not like a C-cast. – Edward Strange Nov 05 '10 at 16:42
  • The primary difference is that reinterpret_cast won't cast away constness, which I noted. Other than that, saying that reinterpret_cast cast is similar to a plain C-cast, in the sense that you can simply "reinterpret" a bit-pattern as a different type when casting a pointer type to another pointer type, seems perfectly valid. The differences are subtle enough that using the word "similar" is fine here. Even though the C++ standard allows implementations to alter the bit-pattern on a reinterpret_cast, ultimately, casting between two unrelated types is just as dangerous either way. – Charles Salvia Nov 05 '10 at 17:11
-1

reinterpret_cast is pretty equivalent to a C-style cast. It doesn't guarentee anything; it's there to allow you to do what you need to, in the hopes that you know what you're doing.

If you're looking to ensure safety, use dynamic_cast, as that's what it does. If the cast cannot be completed safely, dynamic_cast returns NULL or nullptr (C++0x).

Casting using the "casting operators" such as static_cast, dynamic_cast, etc.. cannot be overloaded. Straight conversions can, such as:

class Degrees
{
public:
    operator double() { ... }
};
Chris
  • 452
  • 3
  • 14
  • 2
    A reinterpret_cast is not at all equivalent to a C-style cast. A C-style cast can result in a static_cast and can actually do a couple of very rare things that are impossible with any new-style cast. – Edward Strange Nov 05 '10 at 16:41