Jump to content

  • Log In with Google      Sign In   
  • Create Account

reinterpret_cast examples?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
40 replies to this topic

#21 frob   Moderators   -  Reputation: 22697

Like
0Likes
Like

Posted 01 May 2013 - 02:01 PM

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.


Check out my book, Game Development with Unity, aimed at beginners who want to build fun games fast.

Also check out my personal website at bryanwagstaff.com, where I write about assorted stuff.


Sponsor:

#22 Paradigm Shifter   Crossbones+   -  Reputation: 5433

Like
0Likes
Like

Posted 01 May 2013 - 02:06 PM

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.


"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#23 achild   Crossbones+   -  Reputation: 1940

Like
0Likes
Like

Posted 01 May 2013 - 02:51 PM

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, 01 May 2013 - 02:52 PM.


#24 frob   Moderators   -  Reputation: 22697

Like
1Likes
Like

Posted 01 May 2013 - 04:06 PM

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.


Check out my book, Game Development with Unity, aimed at beginners who want to build fun games fast.

Also check out my personal website at bryanwagstaff.com, where I write about assorted stuff.


#25 noatom   Members   -  Reputation: 785

Like
0Likes
Like

Posted 01 May 2013 - 05:37 PM

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?



#26 Brother Bob   Moderators   -  Reputation: 8575

Like
1Likes
Like

Posted 01 May 2013 - 05:50 PM

No, with multiple inheritance the reinterpret_cast will just cast the pointer, but static_cast will correctly adjust the pointer for the different base classes. Base and derived types are related, so you use static_cast which is used to cast between related types.

 

That's the difference between the two that I hinted at earlier; reinterpret_cast will just cast the type, but static_cast will also cast the value if necessary.



#27 achild   Crossbones+   -  Reputation: 1940

Like
0Likes
Like

Posted 01 May 2013 - 07:14 PM

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.

Fantastic point! That is very easy for me to forget sometimes. (Though the user may very well have considered this when allocating their image).



#28 noatom   Members   -  Reputation: 785

Like
0Likes
Like

Posted 02 May 2013 - 01:54 AM

No, with multiple inheritance the reinterpret_cast will just cast the pointer, but static_cast will correctly adjust the pointer for the different base classes. Base and derived types are related, so you use static_cast which is used to cast between related types.

 

That's the difference between the two that I hinted at earlier; reinterpret_cast will just cast the type, but static_cast will also cast the value if necessary.

 

Ok,but isn't changing just the type enough? I mean it's a pointer,not an object.



#29 Brother Bob   Moderators   -  Reputation: 8575

Like
1Likes
Like

Posted 02 May 2013 - 02:37 AM

No, changing the type is not enough.

struct base1 { };
struct base2 { };
struct derived : base1, base2 { };

int main(int, char**)
{
    base2 *b = new derived;
    base1 *br = reinterpret_cast<derived *>(b);
    base1 *bs = static_cast<derived *>(b);

    std::cout << b << std::endl;
    std::cout << br << std::endl;
    std::cout << bs << std::endl;
}

Here, b is a base2-pointer to a derived object, and br and bs are base1-pointers to the derived object typecast via the derived class using reinterpret_cast and static_cast, respectively.

 

The br pointer is an invalid cast because you have a base1 pointer incorrectly pointing to the base2 subclass of the derived object. The bs pointer is a valid pointer because you have a base1 pointer correctly pointing to the base1 subclass of the derived object.

 

Try the program, the two last pointers should be different. The cast requires changing the pointer's value as well as changing its type.



#30 dmatter   Crossbones+   -  Reputation: 3294

Like
0Likes
Like

Posted 02 May 2013 - 09:34 AM

AFAIK (I am not a language lawyer) the only thing you can safely do after having performed a reinterpret_cast is to cast back again with another reinterpret_cast.

So you could not cast and then use the value for anything because it's implementation defined - in practice specific implementations make useful guarantees about things, but the C++ standard doesn't.

 

So a standards-compliant practical use of reinterpret_cast would be to pass a T* pointer through an API that only accepts, say, a void* or a char*. Then on the other side, you can cast it back to a T*.

 

I'd be interested to know if the standard does offer any additional guarantees?

In any case, use of reinterpret_cast makes me nervous.



#31 SiCrane   Moderators   -  Reputation: 9662

Like
0Likes
Like

Posted 02 May 2013 - 10:14 AM

Other than converting back to the original type, the standard also says that if you convert a null pointer of one type to another pointer type the result will be a null pointer of the new type, so you can check a reinterpret_cast'ed pointer for null. A reinterpret_cast on things like integers and pointers to their own type will also yield the value of the original operand. Pretty much everything is either undefined, unspecified or implementation defined.

#32 King Mir   Members   -  Reputation: 2050

Like
0Likes
Like

Posted 02 May 2013 - 11:38 AM

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.

As far as I know, C-style cast in C++ is defined to try to do a static cast, and if it can't, then do a reinterpret cast. So it should handle multiple inherritance fine. However, if you have a bug and you're doing something where it is not possible to do the cast as a static cast, then the C-style cast will do a reinterpret cast, hiding the bug.

 

There's also constructor-style cast, which works just like C-style cast, except when it calls a constructor.



#33 Brother Bob   Moderators   -  Reputation: 8575

Like
0Likes
Like

Posted 02 May 2013 - 12:10 PM

 

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.

As far as I know, C-style cast in C++ is defined to try to do a static cast, and if it can't, then do a reinterpret cast. So it should handle multiple inherritance fine. However, if you have a bug and you're doing something where it is not possible to do the cast as a static cast, then the C-style cast will do a reinterpret cast, hiding the bug.

I have already discussed the ambiguous nature of the type of cast the C-style cast performs and why it doesn't work with multiple inheritance in some cases. It is because it silently falls back on the incorrect reinterpret_cast that it is dangerous to use.



#34 King Mir   Members   -  Reputation: 2050

Like
0Likes
Like

Posted 02 May 2013 - 12:42 PM




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.


As far as I know, C-style cast in C++ is defined to try to do a static cast, and if it can't, then do a reinterpret cast. So it should handle multiple inherritance fine. However, if you have a bug and you're doing something where it is not possible to do the cast as a static cast, then the C-style cast will do a reinterpret cast, hiding the bug.


I have already discussed the ambiguous nature of the type of cast the C-style cast performs and why it doesn't work with multiple inheritance in some cases. It is because it silently falls back on the incorrect reinterpret_cast that it is dangerous to use.


You discussed why reinterpret_cast does not work with multiple inheritance. C-style cast isn't reinterpret_cast though. It tries to do a static cast first, so correctly written multiple inherritance will work with it.

Yes, C-style casts are bad, but not because of multiple inherritance.

#35 Brother Bob   Moderators   -  Reputation: 8575

Like
0Likes
Like

Posted 02 May 2013 - 01:01 PM

I also said, and so did you, that C-style cast will do a reinterpret_cast if it cannot do the static_cast. When reinterpret_cast is the wrong thing to do in those cases, then so is the C-style that incorrectly proceeds with the cast. It changes the behavior of the cast, and the casting behavior between the two is different in multiple inheritance.



#36 noatom   Members   -  Reputation: 785

Like
1Likes
Like

Posted 02 May 2013 - 03:59 PM

just my humble opinion: everyone should use the c++ explicit casts.It doesn't matter if you're doing a static cast,or a reinterpret cast.If you ever have problems,it will be a lot easier to locate the casts and recognize fast what kind of cast you are doing.

 

 

@Brother Bob,you made a wonderful example showing me why I should use static_cast when the types are releated.Kudos!


Edited by noatom, 02 May 2013 - 04:00 PM.


#37 Paradigm Shifter   Crossbones+   -  Reputation: 5433

Like
0Likes
Like

Posted 02 May 2013 - 05:09 PM

That is the correct answer. C-style casts being difficult to search (find in files, grep) for, and a cause of bugs, is my main gripe with them.


"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#38 Cornstalks   Crossbones+   -  Reputation: 6991

Like
0Likes
Like

Posted 02 May 2013 - 09:34 PM

I'm surprised nobody has linked to this yet. It's been my most useful guide in understanding C++'s different casting abilities.


[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#39 noatom   Members   -  Reputation: 785

Like
0Likes
Like

Posted 03 May 2013 - 07:55 AM

Well,Cornstalks,that's an amazing resource,thanks for sharing.



#40 King Mir   Members   -  Reputation: 2050

Like
0Likes
Like

Posted 03 May 2013 - 01:49 PM

I also said, and so did you, that C-style cast will do a reinterpret_cast if it cannot do the static_cast. When reinterpret_cast is the wrong thing to do in those cases, then so is the C-style that incorrectly proceeds with the cast. It changes the behavior of the cast, and the casting behavior between the two is different in multiple inheritance.

The behavior of a c-style cast is always the same as a static cast, when a static cast is possible, which is is when upcasting multiple ingerritance. So the C cast will correctly upcast.

When static_cast doesn't work, reinterpret cast is probably not wrong; it's the only option. However, it might hide a bug where you expect static cast to be possible, but it isn't. The bug is likely elsewhere, but using static_cast may help catch it, turning a runtime error into a compile time error. But again, this has little to do with multiple inherritance.

Edited by King Mir, 03 May 2013 - 01:58 PM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS