代码之家  ›  专栏  ›  技术社区  ›  Alex319

将多维数组转换成C++中的指针

  •  12
  • Alex319  · 技术社区  · 15 年前

    我有一个程序,如下所示:

    double[4][4] startMatrix;
    double[4][4] inverseMatrix;
    initialize(startMatrix) //this puts the information I want in startMatrix
    

    现在我要计算startmatrix的逆矩阵,并将其放入逆矩阵中。为此,我有一个库函数,其原型如下:

    void MatrixInversion(double** A, int order, double** B)
    

    取a的倒数,放入b,问题是我需要知道如何把双[4][4]转换成双*,给函数。我试过用“显而易见的方式”来做:

    MatrixInversion((double**)startMatrix, 4, (double**)inverseMatrix))
    

    但这似乎行不通。这真的是正确的方法吗?

    7 回复  |  直到 7 年前
        1
  •  20
  •   AnT stands with Russia    12 年前

    不,没有正确的方法来专门这样做。一 double[4][4] 数组不能转换为 double ** 指针。这是实现二维数组的两种可选的、不兼容的方法。需要更改一些内容:函数的接口或作为参数传递的数组的结构。

    实现后者的最简单方法,即 双[4][4] 数组与函数兼容,是创建临时的“索引”数组类型 double *[4] 指向每个矩阵中每一行的开头

    double *startRows[4] = { startMatrix[0], startMatrix[1], startMatrix[2] , startMatrix[3] };
    double *inverseRows[4] = { /* same thing here */ };
    

    而是传递这些“索引”数组

    MatrixInversion(startRows, 4, inverseRows);
    

    一旦函数完成工作,您就可以忘记 startRows inverseRows 数组,因为结果将被放入原始 inverseMatrix 正确排列。

        2
  •  5
  •   UncleBens    15 年前

    由于二维数组(一个连续的内存块)和指针数组(不连续的)是非常不同的,所以不能将二维数组传递给使用指针到指针的函数。

    你可以做的一件事是:模板。将第二个维度的大小设置为模板参数。

    #include <iostream>
    
    template <unsigned N>
    void print(double a[][N], unsigned order)
    {
        for (unsigned y = 0; y < order; ++y) {
            for (unsigned x = 0; x < N; ++x) {
                std::cout << a[y][x] << ' ';
            }
            std::cout << '\n';
        }
    }
    
    int main()
    {
        double arr[3][3] = {{1, 2.3, 4}, {2.5, 5, -1.0}, {0, 1.1, 0}};
        print(arr, 3);
    }
    

    另一种更笨拙的方法可能是让函数接受一个指向一维数组的指针,并将宽度和高度作为参数给出,然后自己将索引计算为二维表示。

    #include <iostream>
    
    void print(double *a, unsigned height, unsigned width)
    {
        for (unsigned y = 0; y < height; ++y) {
            for (unsigned x = 0; x < width; ++x) {
                std::cout << a[y * width + x] << ' ';
            }
            std::cout << '\n';
        }
    }
    
    int main()
    {
        double arr[3][3] = {{1, 2.3, 4}, {2.5, 5, -1.0}, {0, 1.1, 0}};
        print(&arr[0][0], 3, 3);
    }
    

    当然,一个矩阵应该有它自己的类(但是如果您需要编写助手函数,上面的内容可能仍然是相关的)。

        3
  •  2
  •   James Eichele Bernard Igiri    15 年前

    既然你正在使用C++,这样做的正确方法是使用自定义类和一些模板。下面的示例相当粗糙,但它得到了基本的要点。

    #include <iostream>
    
    using namespace std;
    
    template <int matrix_size>
    class SquareMatrix
    {
        public:
            int size(void) { return matrix_size; }
            double array[matrix_size][matrix_size];
            void copyInverse(const SquareMatrix<matrix_size> & src);
            void print(void);
    };
    
    template <int matrix_size>
    void SquareMatrix<matrix_size>::copyInverse(const SquareMatrix<matrix_size> & src)
    {
        int inv_x;
        int inv_y;
    
        for (int x = 0; x < matrix_size; x++)
        {
            inv_x = matrix_size - 1 - x;
            for (int y = 0; y < matrix_size; y++)
            {
                inv_y = matrix_size - 1 - y;
                array[x][y] = src.array[inv_x][inv_y];
            }
        }
    }
    
    template <int matrix_size>
    void SquareMatrix<matrix_size>::print(void)
    {
        for (int y = 0; y < 4; y++)
        {
            for (int x = 0; x < 4; x++)
            {
                cout << array[x][y] << " ";
            }   
            cout << endl;
        }
    }
    
    template <int matrix_size>
    void Initialize(SquareMatrix<matrix_size> & matrix);
    
    int main(int argc, char * argList[])
    {
        SquareMatrix<4> startMatrix;
        SquareMatrix<4> inverseMatrix;
    
        Initialize(startMatrix);
    
        inverseMatrix.copyInverse(startMatrix);
    
        cout << "Start:" << endl;
        startMatrix.print();
    
        cout << "Inverse:" << endl;
        inverseMatrix.print();
    
        return 0;
    }
    
    template <int matrix_size>
    void Initialize(SquareMatrix<matrix_size> & matrix)
    {
        for (int x = 0; x < matrix_size; x++)
        {
            for (int y = 0; y < matrix_size; y++)
            {
                matrix.array[x][y] = (x+1)*10+(y+1);
            }
        }
    }
    
        4
  •  1
  •   leiz    15 年前

    二维数组不是指向指针或类似对象的指针。StartMatrix的正确类型是 double (*)[4] . 对于您的功能,签名应如下:

    MatrixInversion( double (*A)[4], int order, double (*B)[4] );
    
        5
  •  0
  •   Cloud Cho    7 年前

    有一个使用指向的指针的解决方案 bobobobo

    William Sherif(BOBOBOBO)使用了C版本,我只想展示BBOBOBOO的C++版本。

    int numRows = 16 ;
    int numCols = 5 ;
    int **a ;
    
    a = new int*[ numRows* sizeof(int*) ];
    for( int row = 0 ; row < numRows ; row++ )
    {
        a[row] = new int[ numCols*sizeof(int) ];
    }
    

    其余代码与bobobobobo的相同。

        6
  •  -1
  •   David    15 年前

    问题是二维数组与指针数组不同。二维数组一行接一行地存储元素,因此,当传递这样的数组时,只会给出指向开始的指针。接收函数可以计算出如何查找数组的任何元素,但是 只有知道每行的长度 .

    所以,您的接收函数应该声明为 void MatrixInversion(double A[4][], int order, double B[4][]) .

        7
  •  -2
  •   Test    15 年前

    如果C++:

    struct matrix {
        double m[4][4];
    };
    
    matrix startMatrix;
    matrix inverseMatrix;
    

    所以 界面 将是

    void MatrixInversion(matrix &A, int order, matrix &B);
    

    并使用它

    MatrixInversion(startMatrix, 4, inverseMatrix);
    

    好处

    1. 界面非常简单明了。
    2. 一旦需要在内部修改矩阵的“m”,就不需要更新接口。

    或者这样

    struct matrix {
        void Inversion(matrix &inv, int order) {...}
    protected:
        double m[4][4];
    };
    
    matrix startMatrix;
    matrix inverseMatrix;
    ...
    

    C语言中的一种丑陋的方式

    void MatrixInversion(void *A, int order, void *B);
    MatrixInversion((void*)startMatrix, 4, (void*)inverseMatrix);
    

    编辑:不会崩溃的MatrixinVersion的参考代码:

    void MatrixInversion(void *A, int order, void *B)
    {
        double _a[4][4];
        double _b[4][4];
    
        memcpy(_a, A, sizeof _a);
        memcpy(_b, B, sizeof _b);
        // processing data here
    
        // copy back after done
        memcpy(B, _b, sizeof _b);
    }