Sign in to follow this  
noatom

reinterpret_cast examples?

Recommended Posts

noatom    927

I've been reading a little bit about reinterpret_cast,and I have a problem thinking about when I could really use it.I can use it to cast a pointer to a totally unreleated type of pointer.

 

Are there some good examples to show some situations you can't solve without reinterpret_cast?

Share this post


Link to post
Share on other sites

Well, a C-style cast trumps everything (can do all types of casts).

 

One use is to get the binary representation of a float, reinterpret_cast the address to an int*, so you can do bit-twiddling operations on it (like clearing or setting the sign bit, stuff like that).

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites
Brother Bob    10344

I've been reading a little bit about reinterpret_cast,and I have a problem thinking about when I could really use it.I can use it to cast a pointer to a totally unreleated type of pointer.

reinterpret_cast is for casting between unrelated types, so yes, you can use it to cast a pointer of one type to a pointer of another unrelated type.

 

Are there some good examples to show some situations you can't solve without reinterpret_cast?

Well, casting between unrelated pointer types requires a cast, and a reinterpret_cast is the cast for that.

Share this post


Link to post
Share on other sites
Brother Bob    10344

Well, a C-style cast trumps everything (can do all types of casts).

That is actually not true. It cannot do casts of pointer to classes with multiple inheritance in some cases. The C-style cast will just reinterpret the pointer value, but a proper C++ style cast may actually change the value to handle multiple inheritance correctly.

Share this post


Link to post
Share on other sites

Well, you learn something new every day ;)

 

What used to happen before the new C++ casts? They're templated and were templates introduced at the same time as multiple inheritance? (EDIT: presumably virtual inheritance was a problem? EDIT2: Hmm I guess all MI would be a problem with a C-style cast presumably you had to add on the sizeof the first base to cast to the 2nd via a cast to char*)

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites
ApochPiQ    23003
reinterpret_cast<> is just slightly less evil than const_cast<> IMO. It generally should only be used in dire circumstances and/or where there is a need to interact with poorly specified code and/or code from languages other than C++.

One concrete example is moving from void* to any other pointer type. If you use void* to represent "any pointer type possible", the correct way to recover a real pointer is with reinterpret_cast<>. This can be useful when a C-style API (such as the Windows API) requires a void* as an opaque parameter but you know the actual type that should be passed through; examples include any callback system with a custom parameter in the Windows API.

Share this post


Link to post
Share on other sites
Brother Bob    10344

Well, you learn something new every day ;)

 

What used to happen before the new C++ casts? They're templated and were templates introduced at the same time as multiple inheritance? (EDIT: presumably virtual inheritance was a problem? EDIT2: Hmm I guess all MI would be a problem with a C-style cast presumably you had to add on the sizeof the first base to cast to the 2nd via a cast to char*)

I have to correct me a bit, but I'm still a bit uncertain about the exact details so keep that in mind.

 

It seems to be that is not that C-style cast cannot cast with multiple inheritance which I implied, but that the behavior of the C-style cast can silently change. The correct way to cast between base classes in multiple inheritance, as I understand it, is via static_cast and derived classes. The C-style cast will do the right thing if if the full definition of the inheritance hierarchy is present. If not, the C-style cast will go ahead and do an incorrect reinterpret_cast, while the correct static_cast will fail.

 

The C-style cast will therefore cast correctly when the cast is doable, but will silently work and do the wrong thing when the cast cannot be done correctly.

Share this post


Link to post
Share on other sites
noatom    927

reinterpret_cast<> is just slightly less evil than const_cast<> IMO. It generally should only be used in dire circumstances and/or where there is a need to interact with poorly specified code and/or code from languages other than C++.

One concrete example is moving from void* to any other pointer type. If you use void* to represent "any pointer type possible", the correct way to recover a real pointer is with reinterpret_cast<>. This can be useful when a C-style API (such as the Windows API) requires a void* as an opaque parameter but you know the actual type that should be passed through; examples include any callback system with a custom parameter in the Windows API.

 

what about static cast? shouldn't i use it exactly for that?

Share this post


Link to post
Share on other sites

Yeah, I thought static_cast would be good enough to cast from void* and back? reinterpret_cast is for when you don't want the actual value (i.e. the address held by the pointer) to change I thought...

Share this post


Link to post
Share on other sites
ApochPiQ    23003
Apparently there is some religious debate over whether to use static_cast<> or reinterpret_cast<> for that case. I suggest reading up on the controversy yourself and drawing your own conclusion; I personally prefer reinterpret_cast<> but my reasons are entirely subjective and may not be worth emulating :-)

Share this post


Link to post
Share on other sites

If static_cast works I would use that since as you say it is less evil... reinterpret_cast should be for the case I mentioned earlier (i.e. don't change the address, just cast it to another type, AKA "compiler, I know what I am doing, trust me" cast).

 

EDIT: Multiple inheritance may mess that up though, I suppose. I can't be arsed reading a religious debate about it anyway ;)

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites

Here's what the casts should have been called anyway:

 

static_cast: do_what_you_think_i_mean_and_by_the_way_one_thing_it_is_not_is_static_cast

reinterpret_cast: do_what_i_say_cast

const_cast: i_just_tried_to_annoy_you_by_lying_earlier_about_the_const_thing_cast

 

C-style cast: impossible_to_grep_for_cast. Java and C# really missed the boat on this one by not making it easier to do a search for casts. Visual Studio still hasn't got a "find any cast" search facility, which would be rather handy.

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites
noatom    927

wait...reinterpret cast....what does it exactly do,how does it work? does it just change the address?

 

what about static cast? does actually copy the bits to a new object?

 

Can someone explain how they work? getting really confused here

Share this post


Link to post
Share on other sites

Reinterpret cast doesn't do anything ;) It just says to the compiler "here's this address, treat it as a pointer to this even though that would be illegal, I know what I'm doing".

 

static_cast can do lots of things like point to a different base object in the case of multiple inheritance or casting from a float to an int (completely changes the value, i.e. the very antithesis of "static").

Share this post


Link to post
Share on other sites
Brother Bob    10344

If you want a really quick and basic summary, you can think of it like this:

  • reinterpret_cast is use to change the type but it won't change the underlying bits. For example, change the type of one pointer to another, or to put the value of a pointer in an integer.
  • static_cast is used to change the type and the logical value. For example, if you static_cast from a float to an integer, then the logical value is preserved; that is, if you cast from 1.0f, then the integer value is 1, even though the bits are completely different.

Share this post


Link to post
Share on other sites

Anyway, I think the key lesson from this sermon is that if you have C++ code which uses casts it needs to be refactored into a lower-level interface which hides the gory details from you.

Share this post


Link to post
Share on other sites
noatom    927

with static_cast

 

You can explicitly convert a pointer of a type A to a pointer of a type B if A is a base class of B. If A is not a base class of B, a compiler error will result.

You may cast an lvalue of a type A to a type B& if the following are true:

  • A is a base class of B
  • You are able to convert a pointer of type A to a pointer of type B
  • The type B has the same or greater const or volatile qualifiers than type A
  • A is not a virtual base class of B

The result is an lvalue of type B.

A pointer to member type can be explicitly converted into a different pointer to member type if both types are pointers to members of the same class. This form of explicit conversion may also take place if the pointer to member types are from separate classes, however one of the class types must be derived from the other.

 

 

As if my head wasn't spinning...

Edited by noatom

Share this post


Link to post
Share on other sites

Welcome to the wonderful world of C++ ;)

 

First bullet point is obvious. 2nd involves whether you have defined conversion operators which are public in the class I believe (EDIT: or accessible in the context of the cast e.g. private conversion operators ok in the same class, etc.). 3rd one requires const_cast. Not sure about the virtual inheritance 4th case, I've never used virtual inheritance.

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites
noatom    927

damn...just tested it,you can also convert a value of type b to the base class a without problems.Wondering why they didn't say that....

Share this post


Link to post
Share on other sites

You don't need a cast for that... although it does slice the object if you pass or copy by value (EDIT: And virtual functions won't work if you cast a Derived to a Base class). In C you would need a cast which is why well written C++ requires less casting shenanigans than C.

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites
frob    44904

Not sure about the virtual inheritance 4th case, I've never used virtual inheritance.

It is not used very often, but it solves a nasty problem of inheritance trees.  See the article in Wikipedia for a description of the problem.

 

The standard libraries use it in several places, such as the I/O libraries.

 

Other than that, I have only seen it used a handful of times over decades of programming.

Share this post


Link to post
Share on other sites

Yeah, I know what it is used for, I just don't like the sound of it. You can get the same effect with interfaces (abstract base classes) and multiple inheritance, it just requires more cut and paste or reimplementation, can you not? I don't think it's a good replacement for avoiding copy/paste code because of the gnarly problems... it is a hard problem though.

Share this post


Link to post
Share on other sites
popsoftheyear    2194

Concrete example for reinterpret cast:

You create an image buffer of x number of bytes. You calculate by bytes just in case there are issues with scan line alignment in this example. However, when you access each scanline, you know you are working with 32 bit data in your case, so you want to reference each scanline's memory using an unsigned int *.

 

Definitely want reinterpret_cast for that.

 

Example: unsigned int *pScan = reinterpret_cast<unsigned int *>(pBuffer8 + y * scanBytes);

 

Now you can address the pixels on that scan.

Edited by achild

Share this post


Link to post
Share on other sites
frob    44904

Now you can address the pixels on that scan.

With the caveat that the memory must be properly aligned.

 

The x86 family is almost unique that it will allow misaligned integer access.  There is a nasty performance penalty for each read.  

 

Most systems will simply crash on that line if you aren't lucky enough to have a correct alignment.

Share this post


Link to post
Share on other sites
noatom    927

You can explicitly convert a pointer of a type A to a pointer of a type B if A is a base class of B. -> using static _cast

 

But isn't that the same thing a reinterpret_cast would do? What's the difference?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this