![]() |
|
|
|||||||
![]() |
C++ - casting pointers/arrays to multidimensional arrays |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
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 |
|
|
|
|
#2 |
|
Posts: n/a
|
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 |
|
|
|
#3 |
|
Posts: n/a
|
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 |
|
![]() |
| Thread Tools | Search this Thread |
|
|