I recently learned that it is Undefined Behavior to reinterpret a POD as a different POD by reinterpret_cast
ing its address. So I'm just wondering what a potential use-case of reinterpret_cast
might be, if it can't be used for what its name suggests?
There are two situations in which I’ve used reinterpret_cast
:
To cast to and from
char*
for the purpose of serialisation or when talking to a legacy API. In this case the cast fromchar*
to an object pointer is still strictly speaking UB (even though done very frequently). And you don’t actually needreinterpret_cast
here — you could usememcpy
instead, but the cast might under specific circumstances avoid a copy (but in situations where reinterpreting the bytes is valid in the first place,memcpy
usually doesn’t generate any redundant copies either, the compiler is smart enough for that).To cast pointers from/to
std::uintptr_t
to serialise them across a legacy API or to perform some non-pointer arithmetic on them. This is definitely an odd beast and doesn’t happen frequently (even in low-level code) but consider the situation where one wants to exploit the fact that pointers on a given platform don’t use the most significant bits, and these bits can thus be used to store some bit flags. Garbage collector implementations occasionally do this. The lower bits of a pointer can sometimes also be used, if the programmer knows that the pointer will always be aligned e.g. at an 8 byte boundary (so the lowest three bits must be 0).
But to be honest I can’t remember the last concrete, legitimate situation where I’ve actually used reinterpret_cast
. It’s definitely many years ago.
reinterpret_cast
as a way to say to a following developer "This is probably undefined behavior but we have to do it because it's how this API works, here be dragons" in a nice searchable package. If it was safe you'd be using static_cast
–
Exhibition reinterpret_cast
’s purpose, at least nowadays, is definitely not to exploit UB. You really shouldn’t ever rely on UB (ignoring some standards defects). You can rely on implementation-defined behaviour, but that‘s fundamentally different. reinterpret_cast
helps exploit implementation-defined behaviour, not UB. But you’re right that historically UB used to be treated in a more blasé fashion, and some platform APIs outright required UB. –
Breana reinterpret_cast
is basically a good way to indicate something has dragons associated even if they aren't technically UB. Things like casting a pointer through void*
for example. Yes you can do it with static_cast
but it's a better indication to the following developer to use reinterpret_cast
to indicate the danger. –
Exhibition static_cast
in this situation is definitely better, because it indicates that the result of the cast is well-defined, safe and does exactly what’s expected. reinterpret_cast
, if anything, give the impression “I don’t know exactly what I’m doing”. Always prefer the narrowest available cast, only drop to more permissible casts if you have to. –
Breana reinterpret_cast
where static_cast
works. Even ignoring other reasons, this is error-prone! Because the compiler will save you from yourself if you’re using static_cast
but are accidentally trying to cast the wrong type. With reinterpret_cast
the compiler gives up and won’t catch many silly mistakes that using static_cast
will prevent. –
Breana void*
I'll extremely disagree. It's not safe despite being defined. Using reinterpret_cast
makes it quickly searchable in a codebase, static_cast
does not. For the simple reason you mention above, that you should be using it. So unless you make your own inline fake cast mine::dangerous_cast
I'd use reinterpret_cast
so it's easy to find. –
Exhibition reinterpret_cast
makes the code less safe. reinterpret_cast
may be a warning sign in your personal coding style, but it’s also the cause of errors. At any rate, void*
itself is sufficient warning. Relying on reinterpret_cast
as a warning sign is completely redundant. –
Breana Conforming implementations of C and C++ are allowed to extend the semantics of C or C++ by behaving meaningfully even in cases where the Standards would not require them to do so. Implementations that do so will may be more suitable for a wider range of tasks than implementations that do not. In many cases, it is useful to have consistent syntax to specify constructs which will be processed meaningfully and consistently by implementations that are designed to be suitable for low-level programming tasks, even if implementations which are not designed to be suitable for such purposes would process them nonsensically.
One very frequent use case is when you're working with C library functions that take an opaque void *
that gets forwarded to a callback function. Using reinterpret_cast
on both sides of the fence, so to speak, keeps everything proper.
reinterpret_cast
to cast object pointers to/from void*
(you need it for objects, but that’s UB, though still done). –
Breana static_cast
works (and I would have said is preferable?) –
Harpist reinterpret_cast
is preferable although you can do it with static_cast
. The reasoning being that use of reinterpret_cast
should always indicate danger. Casting through void*
is always a point of danger IMO. –
Exhibition void*
is a static_cast
, and to un-do an implicit conversion you also use static_cast
. It is the proper one to use for this. –
Riesling © 2022 - 2024 — McMap. All rights reserved.
void *
– Gossettreinterpret_cast
to convert object pointers fromvoid*
– Kildarestd::array<double,2>
. – Fancifulreinterpret_cast
for that. Usestatic_cast
. – Breanastatic_cast
was for upcast only. – Romeureinterpret_cast
s. For example, window messages often have a pointer passed in as an integral type and you're expected to cast it back. – Catherinereinterpret_cast
here. Note that most of those use cases are not actually useful. For example, converting an object to its own type or simply allowing a back-and-forth between two types with the intermediate value being otherwise unusable (ex. can convertA
toB
but usingB
is UB, though it can be converted back toA
). – Leontine