Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it Legal to reinterpret_cast to a void*

I was looking at https://en.cppreference.com/w/cpp/language/reinterpret_cast and I noticed that it specifies the legal types we can always cast to:

  • byte*
  • char*
  • unsigned char*

But I did not see void* in the list. Is this an oversight? My use case requires a reinterpret_cast because I'm casting from an int** to a void*. And I will eventually cast from the void* back to an int**.

like image 219
Jonathan Mee Avatar asked Apr 17 '19 13:04

Jonathan Mee


People also ask

What is Reinterpret_cast used for?

The reinterpret_cast allows the pointer to be treated as an integral type. The result is then bit-shifted and XORed with itself to produce a unique index (unique to a high degree of probability). The index is then truncated by a standard C-style cast to the return type of the function.

Can you cast a void pointer?

A void pointer can hold address of any type and can be typecasted to any type.

Is typecast from void * into int * Possible?

void *p = malloc(n * sizeof(int)); int *q = (int *) p; int *q = p; // implicit type cast from void * to int * is allowed! int *q = malloc(n * sizeof(int)); // same as int *q = p.

Is reinterpret cast Safe?

Reinterpret casts are only available in C++ and are the least safe form of cast, allowing the reinterpretation of the underlying bits of a value into another type. It should not be used to cast down a class hierarchy or to remove the const or volatile qualifiers.


1 Answers

Those types are exempt from strict aliasing rules. It does not mean they are the only type you can use with reinterpret_cast. In the case of casting an object pointer to another object pointer type, failing to meet the requirements of strict aliasing rules means you cannot safely dereference the result. But you can still cast the resulting pointer back to the original type safely, and use the result as-if it was the original pointer.

The relevant section from cppreference on reinterpret_cast :

(Any object pointer type T1* can be converted to another object pointer type cv T2*. This is exactly equivalent to static_cast<cv T2*>(static_cast<cv void*>(expression)) (which implies that if T2's alignment requirement is not stricter than T1's, the value of the pointer does not change and conversion of the resulting pointer back to its original type yields the original value). In any case, the resulting pointer may only be dereferenced safely if allowed by the type aliasing rules)

When casting back to the original type, AliasedType and DynamicType are the same, so they are similar, which is the first case listed by the aliasing rules where it is legal to dereference the result of reinterpret_cast :

Whenever an attempt is made to read or modify the stored value of an object of type DynamicType through a glvalue of type AliasedType, the behavior is undefined unless one of the following is true:

  • AliasedType and DynamicType are similar.
  • AliasedType is the (possibly cv-qualified) signed or unsigned variant of DynamicType.
  • AliasedType is std::byte, (since C++17)char, or unsigned char: this permits examination of the object representation of any object as an array of bytes.
like image 79
François Andrieux Avatar answered Oct 01 '22 20:10

François Andrieux