Rob*_*lck 3 c c++ arrays multidimensional-array
如果我有一个内部使用3x3矩阵的函数,但由于API的限制必须传递一个由9个元素组成的连续数组,有没有办法将数组基本上转换为2d数组?
以下方法不起作用,但希望它传达了我正在尝试做的事情.
我知道像Eigen这样的软件包让这件事变得微不足道,但不幸的是,在这种情况下,它不适合我.
void transpose_3x3( double x[3][3] ) {
...
}
void foo( double x[9], double y[3][3] ) {
transpose_3x3(y) // OK
double *my_x[3][3] = &x[0];
transpose_3x3(&my_x); // How?
}
Run Code Online (Sandbox Code Playgroud)
编辑
感谢Daniel向我展示了演员的正确目标,我能够使用C++ reinterpret_cast函数来实现这一目标.虽然union和memcpy解决方案有效,但是单个显式转换似乎是最直接的解决方案,恕我直言.
#include <iostream>
void print_matrix( double x[3][3] ) {
for(unsigned int i=0; i< 3; i++) {
for(unsigned int j=0; j<3; j++) {
std::cout << x[i][j] << " ";
}
std::cout << std::endl;
}
}
int main() {
double a[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
double (*b)[3] = reinterpret_cast<double (*)[3]>(a);
print_matrix(b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我想不出有办法做一个明确的演员表.
但是你可以记住它.对memcpy的调用并不像你想象的那么愚蠢.编译器经常会看到2位数据实际上代表相同的东西,memcpy是固定大小并优化实际副本.
我必须说我从来没有尝试过与你正在做的矩阵一样大的东西,但我不明白为什么它不起作用.
编辑:事实上我以为我会试一试.我写了以下代码:
void transpose_3x3( double (*x)[3][3] )
{
const double t01 = (*x)[0][1];
const double t02 = (*x)[0][2];
const double t12 = (*x)[1][2];
(*x)[0][1] = (*x)[1][0];
(*x)[0][2] = (*x)[2][0];
(*x)[1][0] = t01;
(*x)[1][2] = (*x)[2][1];
(*x)[2][0] = t02;
(*x)[2][1] = t12;
}
void foo()
{
double x[9] = { 1.0f, 2.0f, 3.0f,
4.0f, 5.0f, 6.0f,
7.0f, 8.0f, 9.0f };
double y[3][3];
memcpy( y, x, sizeof( double ) * 9 );
transpose_3x3( &y );
printf( "%f, %f, %f\n", y[0][0], y[0][1], y[0][2] );
printf( "%f, %f, %f\n", y[1][0], y[1][1], y[1][2] );
printf( "%f, %f, %f\n", y[2][0], y[2][1], y[2][2] );
}
Run Code Online (Sandbox Code Playgroud)
并使用VS2010在发布模式下构建它.
生成的程序集如下:
void foo()
{
00E11000 push ebp
00E11001 mov ebp,esp
00E11003 and esp,0FFFFFFC0h
00E11006 sub esp,0B8h
double x[9] = { 1.0f, 2.0f, 3.0f,
00E1100C fld1
00E1100E push esi
00E1100F fstp qword ptr [esp+2Ch]
00E11013 push edi
00E11014 fld qword ptr [__real@4000000000000000 (0E12138h)]
4.0f, 5.0f, 6.0f,
7.0f, 8.0f, 9.0f };
double y[3][3];
memcpy( y, x, sizeof( double ) * 9 );
transpose_3x3( &y );
printf( "%f, %f, %f\n", y[0][0], y[0][1], y[0][2] );
00E1101A sub esp,18h
00E1101D fstp qword ptr [esp+50h]
00E11021 mov ecx,12h
00E11026 fld qword ptr [__real@4008000000000000 (0E12130h)]
00E1102C lea esi,[esp+48h]
00E11030 fstp qword ptr [esp+58h]
00E11034 lea edi,[esp+90h]
00E1103B fld qword ptr [__real@4010000000000000 (0E12128h)]
00E11041 fst qword ptr [esp+60h]
00E11045 fld qword ptr [__real@4014000000000000 (0E12120h)]
00E1104B fstp qword ptr [esp+68h]
00E1104F fld qword ptr [__real@4018000000000000 (0E12118h)]
00E11055 fstp qword ptr [esp+70h]
00E11059 fld qword ptr [__real@401c000000000000 (0E12110h)]
00E1105F fst qword ptr [esp+78h]
00E11063 fld qword ptr [__real@4020000000000000 (0E12108h)]
00E11069 fstp qword ptr [esp+80h]
00E11070 fld qword ptr [__real@4022000000000000 (0E12100h)]
00E11076 fstp qword ptr [esp+88h]
00E1107D rep movs dword ptr es:[edi],dword ptr [esi]
00E1107F fstp qword ptr [esp+10h]
00E11083 fstp qword ptr [esp+8]
00E11087 fld qword ptr [esp+90h]
00E1108E fstp qword ptr [esp]
00E11091 mov esi,dword ptr [__imp__printf (0E120A0h)]
00E11097 push offset string "%f, %f, %f\n" (0E120F4h)
00E1109C call esi
printf( "%f, %f, %f\n", y[1][0], y[1][1], y[1][2] );
00E1109E add esp,4
00E110A1 fld qword ptr [esp+0C8h]
00E110A8 fstp qword ptr [esp+10h]
00E110AC fld qword ptr [esp+0B0h]
00E110B3 fstp qword ptr [esp+8]
00E110B7 fld qword ptr [__real@4000000000000000 (0E12138h)]
00E110BD fstp qword ptr [esp]
00E110C0 push offset string "%f, %f, %f\n" (0E120F4h)
00E110C5 call esi
printf( "%f, %f, %f\n", y[2][0], y[2][1], y[2][2] );
00E110C7 fld qword ptr [esp+0D4h]
00E110CE add esp,4
00E110D1 fstp qword ptr [esp+10h]
00E110D5 fld qword ptr [__real@4018000000000000 (0E12118h)]
00E110DB fstp qword ptr [esp+8]
00E110DF fld qword ptr [__real@4008000000000000 (0E12130h)]
00E110E5 fstp qword ptr [esp]
00E110E8 push offset string "%f, %f, %f\n" (0E120F4h)
00E110ED call esi
00E110EF add esp,1Ch
}
Run Code Online (Sandbox Code Playgroud)
你会注意到没有memcpy.实际上,它所做的只是手动将矩阵从x复制到y,然后以转置方式打印.基本上有趣的是看看编译器会做些什么来优化事情......
编辑2:当然,在看到paddy的出色反应后再想一想,我发现你可以直接判断事情
transpose_3x3( (double (*)[3][3])&x );
Run Code Online (Sandbox Code Playgroud)
哪个没有memcpy或联合:D
嗯,这有点脏,但你可以使用union铸造.有人会告诉我这个,但无论如何我都会发布它=)
#include <iostream>
using namespace std;
typedef union {
double linear[9];
double square[3][3];
} Matrix;
void transpose_3x3( double x[3][3] )
{
for( int i = 0; i < 3; i++ ) {
for( int j = 0; j < 3; j++ ) {
cout << i << "," << j << ": " << x[i][j] << endl;
}
}
}
void foo( double x[9], double y[3][3] )
{
transpose_3x3( y );
transpose_3x3( ((Matrix*)x)->square );
}
int main()
{
double x[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
double y[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
foo( x, y );
return 0;
}
Run Code Online (Sandbox Code Playgroud)