Небезопасно смешивать статические и реинтерпрет-литые при бросании в void и обратно?

Просто: Если я static_cast тип X* - void*, всегда ли безопасно reinterpret_cast вернуть его в X *?

Я не могу выполнить какой-либо случай, если это не удается, например:

#include <iostream>

struct a
{
    int* m_array;
};

int main()
{
    bool fail = false;

    for(int i = 0; ++i < 5000;)
    {
        a* pA = new a;
        pA->m_array = new int [i+1]; // A new size of data everytime
        pA->m_array[i] = 10;

        void* pvA = static_cast<void*>(pA);
        pA = reinterpret_cast<a*>(pvA);

        if(pA->m_array[i] != 10)
        {
            fail = true;
            break;
        }

        delete []pA->m_array;
        delete pA;
    }

        if(fail)
            std::cout<<"FAILED!!";
        else
            std::cout<<"Never failed :/";
}

Ссылка на скомпилированный пример

Дает результат "Никогда не сработал:/" в обоих режимах отладки и выпуска с vs 2012. Однако это, скорее всего, поведение undefined. Правильно?

Ответ 1

Он четко определен. Согласно ISO/IEC 14882: 2011 [expr.reinterpret.cast] §7 (основное внимание):

Указатель объекта может быть явно преобразован в указатель объекта другой тип. Когда prvalue v типа "указатель на T1" является преобразованный в тип "указатель на cv T2", результатом является static_cast < cv T2 * > (static_cast < cv void * > (v)), если оба T1 и T2 являются стандартными макетами типы (3.9) и требования к выравниванию T2 не являются более строгими, чем те из T1, или если любой тип недействителен.