3

Simply: If i static_cast a type X* to void*, is it always safe to reinterpret_cast it back to X*?

I am unable to produce any case where this fails for example:

#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 :/";
}

Link to compiled example

Gives the result "Never failed :/" in both debug and release mode with vs 2012. However this is most likely undefined behavior. Right?

David
  • 818
  • 13
  • 30
  • 2
    This is well-defined behaviour, that is exactly what `reinterpret_cast` is for: http://stackoverflow.com/a/573345/726361 However you can use `static_cast` to cast from `void*`. – Seth Carnegie May 11 '13 at 17:15
  • 2
    I'd say it's well defined, but can't back it up :( – Luchian Grigore May 11 '13 at 17:15
  • @SethCarnegie The answer you link to contradicts your comment, unless I'm misreading. –  May 11 '13 at 17:16
  • @SethCarnegie He never speaks about mixing the casts as in this case. – David May 11 '13 at 17:16
  • @hvd how so? @ David it doesn't matter. – Seth Carnegie May 11 '13 at 17:40
  • @SethCarnegie That answer says the value of `b = reinterpret_cast(a)` is unspecified (implying it may be different from `static_cast(a)`), and you need `c = reinterpret_cast(b)` to convert it back, you cannot convert it back with `static_cast(b)`. (Actually, this question asks about mixing the two casts the other way.) –  May 11 '13 at 17:45

1 Answers1

3

It is well-defined. As per ISO/IEC 14882:2011 [expr.reinterpret.cast]§7 (emphasis mine):

An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of type “pointer to T1” is converted to the type “pointer to cv T2”, the result is static_cast<cv T2*>(static_cast<cv void*>(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment requirements of T2 are no stricter than those of T1, or if either type is void.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • 2
    That text has changed in C++11, though. I wonder if it was also well-defined earlier? –  May 11 '13 at 17:28
  • 2
    I like to state the version of the standard when I quote from it. That way if you are not using the latest a quick check is easy. – Martin York May 11 '13 at 20:27