c++ - 在 C/C++ 中将数组转换为矩阵?

标签 c++ c arrays multidimensional-array

如果我有一个内部使用 3x3 矩阵的函数,但由于 API 的限制必须向它传递一个包含九个元素的连续数组,是否有一种方法可以将数组转换为二维数组?

以下方法行不通,但希望它能传达我正在尝试做的事情。

我知道像 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?

}

编辑

感谢 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;
}

最佳答案

我想不出一种方法来进行显式转换。

但是你可以只 memcpy 它。调用 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] );
}

并使用 VS2010 在 Release模式下构建它。

生成的程序集如下:

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  
}

您会注意到没有 memcpy。实际上它所做的就是手动将矩阵从 x 复制到 y,然后以转置方式打印它。基本上,看看编译器会做些什么来优化事情是很有趣的……

编辑 2:当然,在看到 paddy 的出色响应后,我想得更远一些,我想到你可以直接用 case 来表示

transpose_3x3( (double (*)[3][3])&x );

在没有 memcpy 或 union 的情况下也能工作 :D

关于c++ - 在 C/C++ 中将数组转换为矩阵?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14247769/

相关文章:

c - 链表、带参数的操作

c - C中结构体的动态内存分配

c++ - std::set 构造函数第二个参数错误

c++ - char *x = "geeksquiz"是什么意思?

使用动态内存压缩文件的行

java - 选择字符串的特定部分

c - 警告 : array subscript is above array bounds [-Warray-bounds] in module

具有可变维度的 JavaScript 函数数组

c++ - 类型错误引用的无效初始化

c++ - 如何在不重叠数字的情况下生成 1 - 39 的随机数?