casting pointers/arrays to multidimensional arrays

Discussion in 'C++' started by Francesco, Nov 3, 2009.

  1. Francesco

    Francesco Guest

    Hi to all,

    would any of you gentlemen please comment on the reinterpret_casts in
    the code below?
    Do you think they're ok or not? Any reference to the standard would be
    greatly appreciated.

    Thank in advance,
    FB

    //CODE
    #include <iostream>
    #include <iomanip>

    typedef float ( * tMtx )[ 4 ];

    void Fill( tMtx inMtx )
    {
    for( int c = 0; c < 16; ++c )
    inMtx[ c / 4 ][ c % 4 ] = c;
    }

    void Print( tMtx inMtx )
    {
    std::cout << "n->" << inMtx << std::endl;
    for( int c1 = 0; c1 < 4; ++c1 )
    {
    for( int c2 = 0; c2 < 4; ++c2 )
    std::cout << std::setw( 5 ) << inMtx[ c1 ][ c2 ];
    std::cout << std::endl;
    }
    std::cout << std::endl;
    }

    int main()
    {
    float mtx1[ 16 ] = { 0 };
    float mtx2[ 4 ][ 4 ];
    float * mtx3 = new float[ 16 ];
    float * mtx4 = reinterpret_cast< float * >( new float[ 4 ][ 4 ] );

    // are these casts OK?
    Fill( reinterpret_cast< tMtx >( mtx1 ) );
    Fill( mtx2 );
    Fill( reinterpret_cast< tMtx >( mtx3 ) );
    Fill( reinterpret_cast< tMtx >( mtx4 ) );

    Print( reinterpret_cast< tMtx >( mtx1 ) );
    Print( mtx2 );
    Print( reinterpret_cast< tMtx >( mtx3 ) );
    Print( reinterpret_cast< tMtx >( mtx4 ) );

    delete[] mtx3;
    delete[] mtx4;

    std::cin.get();
    }
    //ENDCODE
     
    Francesco, Nov 3, 2009
    #1
    1. Advertising

  2. Francesco

    James Kanze Guest

    On Nov 3, 3:41 pm, Francesco <> wrote:

    > would any of you gentlemen please comment on the
    > reinterpret_casts in the code below?
    > Do you think they're ok or not? Any reference to the standard
    > would be greatly appreciated.


    > //CODE
    > #include <iostream>
    > #include <iomanip>


    > typedef float ( * tMtx )[ 4 ];


    > void Fill( tMtx inMtx )
    > {
    > for( int c = 0; c < 16; ++c )
    > inMtx[ c / 4 ][ c % 4 ] = c;
    > }


    > void Print( tMtx inMtx )
    > {
    > std::cout << "n->" << inMtx << std::endl;
    > for( int c1 = 0; c1 < 4; ++c1 )
    > {
    > for( int c2 = 0; c2 < 4; ++c2 )
    > std::cout << std::setw( 5 ) << inMtx[ c1 ][ c2 ];
    > std::cout << std::endl;
    > }
    > std::cout << std::endl;
    > }


    > int main()
    > {
    > float mtx1[ 16 ] = { 0 };
    > float mtx2[ 4 ][ 4 ];
    > float * mtx3 = new float[ 16 ];
    > float * mtx4 = reinterpret_cast< float * >( new float[ 4 ][ 4 ] );


    > // are these casts OK?
    > Fill( reinterpret_cast< tMtx >( mtx1 ) );
    > Fill( mtx2 );
    > Fill( reinterpret_cast< tMtx >( mtx3 ) );
    > Fill( reinterpret_cast< tMtx >( mtx4 ) );


    > Print( reinterpret_cast< tMtx >( mtx1 ) );
    > Print( mtx2 );
    > Print( reinterpret_cast< tMtx >( mtx3 ) );
    > Print( reinterpret_cast< tMtx >( mtx4 ) );


    > delete[] mtx3;
    > delete[] mtx4;


    > std::cin.get();
    > }
    > //ENDCODE


    They're reinterpret_cast. Formally, I think using the results
    of them here is undefined behavior. If you're implementation
    says it's OK, they should work. And in practice, most
    implementations don't say anything, but they work anyway.

    Of course, they're not something you'd want to see in production
    code.

    --
    James Kanze
     
    James Kanze, Nov 3, 2009
    #2
    1. Advertising

  3. Francesco

    Francesco Guest

    On 4 Nov, 13:43, "Daniel T." <> wrote:
    > In article
    > <>,
    >
    >
    >
    >
    >
    >  Francesco <> wrote:
    > > Hi to all,

    >
    > > would any of you gentlemen please comment on the reinterpret_casts in
    > > the code below?
    > > Do you think they're ok or not? Any reference to the standard would be
    > > greatly appreciated.

    >
    > > Thank in advance,
    > > FB

    >
    > > //CODE
    > > #include <iostream>
    > > #include <iomanip>

    >
    > > typedef float ( * tMtx )[ 4 ];

    >
    > > void Fill( tMtx inMtx )
    > > {
    > >     for( int c = 0; c < 16; ++c )
    > >         inMtx[ c / 4 ][ c % 4 ] = c;
    > > }

    >
    > > void Print( tMtx inMtx )
    > > {
    > >     std::cout << "n->" << inMtx << std::endl;
    > >     for( int c1 = 0; c1 < 4; ++c1 )
    > >     {
    > >         for( int c2 = 0; c2 < 4; ++c2 )
    > >             std::cout << std::setw( 5 ) << inMtx[ c1 ][ c2 ];
    > >         std::cout << std::endl;
    > >     }
    > >     std::cout << std::endl;
    > > }

    >
    > > int main()
    > > {
    > >     float mtx1[ 16 ] = { 0 };
    > >     float mtx2[ 4 ][ 4 ];
    > >     float * mtx3 = new float[ 16 ];
    > >     float * mtx4 = reinterpret_cast< float * >( new float[ 4 ][ 4 ] );

    >
    > >     // are these casts OK?
    > >     Fill( reinterpret_cast< tMtx >( mtx1 ) );
    > >     Fill( mtx2 );
    > >     Fill( reinterpret_cast< tMtx >( mtx3 ) );
    > >     Fill( reinterpret_cast< tMtx >( mtx4 ) );

    >
    > >     Print( reinterpret_cast< tMtx >( mtx1 ) );
    > >     Print( mtx2 );
    > >     Print( reinterpret_cast< tMtx >( mtx3 ) );
    > >     Print( reinterpret_cast< tMtx >( mtx4 ) );

    >
    > >     delete[] mtx3;
    > >     delete[] mtx4;

    >
    > >     std::cin.get();
    > > }
    > > //ENDCODE

    >
    > It's doable, but I would do it differently:
    >
    > // begin code
    > typedef float m16[16];
    > typedef float m44[4][4];
    >
    > void Fill(m44& v) {
    >    for(int c = 0; c < 16; ++c)
    >       v[c / 4][c % 4] = c;
    >
    > }  
    >
    > void Fill(m16& v) {
    >    Fill(reinterpret_cast<m44&>(v));
    >
    > }
    >
    > void Print(const m44& v) {
    >    cout << "n->" << v << endl;
    >    for (int c1 = 0; c1 < 4; ++c1) {
    >       for (int c2 = 0; c2 < 4; ++c2)
    >          cout << setw(5) << v[c1][c2];
    >       cout << endl;
    >    }
    >    cout << endl;
    >
    > }
    >
    > void Print(const m16& v) {
    >    Print(reinterpret_cast<const m44&>(v));
    >
    > }
    >
    > int main()
    > {
    >    float mtx1[16] = { 0 };
    >    float mtx2[4][4];
    >
    >    Fill(mtx1);
    >    Fill(mtx2);
    >
    >    Print(mtx1);
    >    Print(mtx2);
    >
    >    cin.get();}
    >
    > // end code
    >
    > Even if you are stuck with the Fill and Print you have, I would still
    > wrap the casts in functions that take the appropriate types. That way
    > you don't have (1) reinterpret_cast all over your code and (2) it is
    > less likely that someone will reinterpret_cast the wrong sort of
    > variable.- Nascondi testo citato
    >
    > - Mostra testo citato -


    Thanks for the answers and hints.
    I was just interested in knowing if casting from a "flat" pointer to a
    multidimensional array (or backwards) is formally defined, undefined
    behavior or implementation defined.
    For the record: I've found an old thread in comp.lang.c where people
    had mixed feelings about the issue and it seems that both standards (C
    and C++) are not that clear on the subject.

    http://groups.google.it/group/comp.lang.c/browse_thread/thread/367141614adee786/

    Summary: the memory layout of something like float [16] should be the
    same as float[4][4] but since the implementation might "magically" do
    different bounds checking (??), the following code might cause trouble
    on some (??) implementations:

    //CODE
    #include <cassert>

    int main()
    {
    float array44[4][4];
    // DEFINED, UB OR IMPLEM DEFINED ?
    float * ptr = reinterpret_cast<float*>( array44 );
    ptr[6] = 123.123;
    assert( (void*)&array44[1][2] == (void*)&ptr[1*4+2] );

    // OPPOSITE CASE
    float array16[16] = {0};
    // DEFINED, UB OR IMPLEM DEFINED ?
    float (*ptr44)[4] = reinterpret_cast<float(*)[4]>( array16 );
    ptr44[1][2] = 123.123;
    assert( (void*)&array16[1*4+2] == (void*)&ptr44[1][2] );
    }

    //ENDCODE

    Again for the record: I'm interested in using the flat to
    multidimensional cast because I'd prefer to use the [][][] in some
    functions that have as input flat arrays (created by somebody else)...
    Thanks a lot again,
    Francesco
     
    Francesco, Nov 6, 2009
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. countofquad
    Replies:
    4
    Views:
    401
    countofquad
    Mar 5, 2005
  2. Replies:
    1
    Views:
    682
    -berlin.de
    Mar 28, 2005
  3. Replies:
    7
    Views:
    590
    Barry Schwarz
    Jun 1, 2005
  4. Philipp
    Replies:
    21
    Views:
    1,190
    Philipp
    Jan 20, 2009
  5. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    739
Loading...

Share This Page