C++: reinterpret_cast v.s. static_cast and memory layout difference

Xianbo QIAN
2 min readJan 6, 2020

--

In C++, reinterpret_cast, static_cast and const_cast is very common. const_cast is pretty easy to understand as it doesn’t change the memory layout and just toggle the const flag for the compiler to help you do or avoid some checks.

The other two is sometimes confusing. Let’s have a look from the memory perspective.

reinterpret_cast will never change the memory layout. It only provides some information for the compiler to generate code. In the assembly code, you won’t see any CPU instructions corresponding to the reinterpret_cast call. However it will affect how other CPU instructions are generated.

const_cast on the other hand, could change the data.

The most reliable and understandable document that I can find is cppreference.com Here is the link to static_cast and reinterpret_cast But here is some quick explanation for basic and common cases. Let’s look at them side by side.

For object pointers. There won’t be any difference between the two, except for multi-inheritance. This wiki page has a good explanation.

Basically if you have a child class depending on two parent classes, the static_cast from child to parent will work correctly but not reintrepret_cast. Why? Remember in C++, parent class stuff (vtable and attributes) are putting upfront, followed by child class stuff. If there are two parent classes, then the result of upcasting to different parent class would be different. Same applies to downcasting.

One thing to notice though is that nullptr_t can’t be convert to other pointer types such as void* or int* using reinterpret_cast because nullptr_t is an object type not a pointer type.

The definition of nullptr_t could be found from LLVM header __nullptr (link), As we can see from the following two lines, it can be converted to pointer type either pointer to an object or a pointer to a class member, using implicit conversion. But nullptr_t itself is an object which has different memory layout compared to other pointer types.

template <class _Tp>        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR        operator _Tp* () const {return 0;}     template <class _Tp, class _Up>        _LIBCPP_INLINE_VISIBILITY        operator _Tp _Up::* () const {return 0;}

// TODO: sign and unsigned integer numbers, float etc.

--

--