Search code examples
c++pointerscastingreinterpret-casttype-punning

Is reinterpret_cast mostly useless?


I've read various previous questions about the use of reinterpret_cast, and I've also read the relevant wording in the C++ standard. Essentially, what it comes down to is that the result of a pointer-to-pointer reinterpret_cast operation can't safely be used for anything other than being cast back to the original pointer type.

In practice, however, most real-world uses of reinterpret_cast seem to be based on the (wrong) assumption that a reinterpret_cast is the same as a C-style cast. For example, I've seen lots of code which uses reinterpret_cast to cast from char* to unsigned char* for the purpose of character set conversion routines. This is completely harmless, yet strictly speaking it's not portable - there's no guarantee that a reinterpret_cast from char* to unsigned char* won't crash your program when you try to dereference the unsigned char* pointer.

It's seems the only other real use of reinterpret_cast that has any real guarantees, according to the standard, is converting from pointer to integer, and vice-versa.

And yet there are many cases where we'd want (and should be able to) safely convert between different pointer types. For example: uint16_t* to the new C++0x char16_t*, or really any pointer to a basic data type that is the same size/alignment as the original type. Yet reinterpret_cast provides no guarantees this should work.

Question: How can we safely convert between pointers to basic data-types of the same size/alignment, such as char* --> unsigned char*? Since reinterpret_cast doesn't seem to guarantee this actually works, are C-style casts the only safe option here?


Solution

  • there's no guarantee that a reinterpret_cast from char* to unsigned char* won't crash your program when you try to dereference the unsigned char* pointer.

    You can't do such a cast in any other way, so you have to have to trust what your compiler does with this completely reasonable cast.

    Since reinterpret_cast doesn't seem to guarantee this actually works, are C-style casts the only safe option here?

    The C-style cast will just map to reinterpret_cast so it will be exactly the same. At some point you have to trust your compiler. The Standard has a limit on which it simply says "no. read your compiler's manual". When it comes to cross-casting pointers, this is such a point. It allows you to read a char using an unsigned char lvalue. A compiler that cannot cast a char* to a usable unsigned char* to do such is just about unusable and doesn't exist for that reason.