Go Back   Velocity Reviews > Newsgroups > C++
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

Reply

C++ - casting pointers/arrays to multidimensional arrays

 
Thread Tools Search this Thread
Old 11-03-2009, 03:41 PM   #1
Default casting pointers/arrays to multidimensional arrays


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
  Reply With Quote
Old 11-03-2009, 04:10 PM   #2
James Kanze
 
Posts: n/a
Default Re: casting pointers/arrays to multidimensional arrays
On Nov 3, 3:41 pm, Francesco <xtrigger...@gmail.com> 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
  Reply With Quote
Old 11-06-2009, 09:04 AM   #3
Francesco
 
Posts: n/a
Default Re: casting pointers/arrays to multidimensional arrays
On 4 Nov, 13:43, "Daniel T." <danie...@earthlink.net> wrote:
> In article
> <f3dab86c-491a-441c-a0ed-7acb69aec...@d21g2000yqn.googlegroups.com>,
>
>
>
>
>
> *Francesco <xtrigger...@gmail.com> 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.l...141614adee786/

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
  Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off




SEO by vBSEO 3.3.2 ©2009, Crawlability, Inc.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46