I know that reinterpret_cast
is primarily used going to or from a char*
.
But I was surprised to find that static_cast
could do the same with a void*
. For example:
auto foo "hello world"s;
auto temp = static_cast<void*>(&foo);
auto bar = static_cast<string*>(temp);
What do we gain from using reinterpret_cast
and char*
over static_cast
and void*
? Is it something to do with the strict aliasing problem?
Your question really has 2 parts:
static_cast
or reinterpret_cast
to work with a pointer to the underlying bit pattern of an object without concern for the object type?reinterpret_cast
is a void*
or a char*
preferable to address this underlying bit pattern?
static_cast
: Converts between types using a combination of implicit and user-defined conversions
In 5.2.9[expr.static.cast]13 the standard, in fact, gives the example:
T* p1 = new T;
const T* p2 = static_cast<const T*>(static_cast<void*>(p1));
It leverages the implicit cast:
A prvalue pointer to any (optionally cv-qualified) object type
T
can be converted to a prvalue pointer to (identically cv-qualified)void
. The resulting pointer represents the same location in memory as the original pointer value. If the original pointer is a null pointer value, the result is a null pointer value of the destination type.*
There is however no implicit cast from a pointer of type T
to a char*
. So the only way to accomplish that cast is with a reinterpret_cast
.
reinterpret_cast
: Converts between types by reinterpreting the underlying bit pattern
So in answer to part 1 of your question when you cast to a void*
or a char*
you are looking to work with the underlying bit pattern, reinterpret_cast
should be used because it's use denotes to the reader a conversion to/from the underlying bit pattern.
Next let's compare void*
to char*
. The decision between these two may be a bit more application dependent. If you are going to use a standard library function with your underlying bit pattern just use the type that function accepts:
void*
is used in the mem
functions provided in the cstring
libraryread
and write
use char*
as inputsIt's notable that C++ specific libraries prefer char*
for pointing to memory.
Holding onto memory as a void*
seems to have been preserved for compatibility reasons as pointer out here. So if a cstring
library function won't be used on your underlying bit patern, use the C++ specific libraries behavior to answer part 2 of your question: Prefer char*
to void*
.