Search code examples
c++alignmentreinterpret-cast

reinterpret_cast and explicit alignment requirement


Given this (bold part) about reinterpret_cast, I was expecting that the piece of code below would generate different addresses when casting X* to Y* since the latter is more striclty aligned than the former. What am I missing here?

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)

cppreference/reinterpret_cast

#include <iostream>


struct alignas (1) X
{
    char c;
};


struct  alignas (32) Y
{
    char c;
};

int main(int argc, const char *const* const argv)
{
    std::cout << alignof(X) << " " << alignof(Y) << std::endl;

    X x;
    Y y;
    std::cout << &x << " " << reinterpret_cast<Y*>(&x) << std::endl;
    std::cout << &y << " " << reinterpret_cast<X*>(&y) << std::endl;

}

output

Program returned: 0
1 32
0x7ffef3434578 0x7ffef3434578
0x7ffef3434540 0x7ffef3434540

snippet on godbolt


Solution

  • Quoting from [expr.reinterpret.cast]/7:

    An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T”, the result is static_­cast<cv T*>(static_­cast<cv void*>(v)).

    Then, from [expr.static.cast]/13:

    A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T”, where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. If the original pointer value represents the address A of a byte in memory and A does not satisfy the alignment requirement of T, then the resulting pointer value is unspecified....

    I believe these rules apply here. In your case, reinterpret_cast<Y*>(&x) is resolved as static_cast<Y*>(static_cast<void*>(&x)). The original pointer value static_cast<void*>(&x) represents the address A and this address generally does not satisfy the alignment requirements of Y. Consequently, the value of the resulting pointer is unspecified.