Reading https://en.cppreference.com/w/cpp/language/reinterpret_cast I wonder what are use-cases of reinterpret_cast
that are not UB and are used in practice?
The above description contains many cases where it is legal to convert a pointer to some other type an then back, which is legal. But that seems of less practical use. Accessing an object through a reinterpret_cast
pointer is mostly UB due to violations of strict-aliasing (and/or alignment), except accessing through a char*
/byte*
-pointer.
One helpful exception is casting a integer-constant to a pointer and accessing the target object, which is useful for manipulation of HW-registers (in µC).
Can anyone tell some real use-cases of relevance of reinterpret_cast that are used in practice?
CodePudding user response:
Some examples that come to mind:
Reading/writing the object representation of an object, for example to write the byte representation of the object to a file and read it back:
// T must be trivially-copyable object type! T obj; //... std::ofstream file(/*...*/); file.write(reinterpret_cast<char*>(obj), sizeof(obj)); //... std::ifstream file(/*...*/); file.read(reinterpret_cast<char*>(obj), sizeof(obj));
Technically it is currently not really specified how accessing the object representation should work, but there is a current proposal to clarify this in the standard, see https://github.com/cplusplus/papers/issues/592.
Obtaining a pointer to a specific memory address. Whether and for which address values this is possible is implementation-defined, as is any possible use of the resulting pointer:
auto ptr = reinterpret_cast<void*>(0x12345678);
Reinterpreting between signed and unsigned variants of the same integral type, especially
char
andunsigned char
for strings, which may be useful if an API expects an unsigned string.auto str = "hello world!"; auto unsigned_str = reinterpret_cast<const unsigned char*>(str);
While this is allowed by the aliasing rules, technically pointer arithmetic on the resulting
unsigned_str
pointer is currently not defined by the standard. But I don't really see why it isn't.Accessing objects nested within a byte buffer (especially on the stack):
alignas(T) std::byte buf[42*sizeof(T)]; new(buf sizeof(T)) T; // later auto ptr = std::launder(reinterpret_cast<T*>(buf sizeof(T)));
This works as long as the address
buf sizeof(T)
is suitably aligned forT
, the buffer has typestd::byte
orunsigned char
, and obviously is of sufficient size. Thenew
expression also returns a pointer to the object, but one might not want to store that for each object. If all objects stored in the buffer are the same type, it would also be fine to use pointer arithmetic on a single such pointer.Casting a
void*
returned bydlsym
(or a similar function) to the actual type of a function located at that address. Whether this is possible and what exactly the semantics are is again implementation-defined:// my_func is a C linkage function with type `void()` in `my_lib.so` // error checking omitted! auto lib = dlopen("my_lib.so", RTLD_LAZY); auto my_func = reinterpret_cast<void(*)()>(dlsym(lib, "my_func"); my_func();