将多维数组转换为 C++ 中的指针
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1584100/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Converting multidimensional arrays to pointers in c++
提问by Alex319
I have a program that looks like the following:
我有一个如下所示的程序:
double[4][4] startMatrix;
double[4][4] inverseMatrix;
initialize(startMatrix) //this puts the information I want in startMatrix
I now want to calculate the inverse of startMatrix and put it into inverseMatrix. I have a library function for this purpose whose prototype is the following:
我现在想计算 startMatrix 的逆并将其放入 inverseMatrix。为此,我有一个库函数,其原型如下:
void MatrixInversion(double** A, int order, double** B)
that takes the inverse of A and puts it in B. The problem is that I need to know how to convert the double[4][4] into a double** to give to the function. I've tried just doing it the "obvious way":
将 A 的倒数放入 B 中。问题是我需要知道如何将 double[4][4] 转换为 double** 以提供给函数。我试过只是用“明显的方式”来做:
MatrixInversion((double**)startMatrix, 4, (double**)inverseMatrix))
but that doesn't seem to work. Is that actually the right way to do it?
但这似乎不起作用。这真的是正确的做法吗?
回答by AnT
No, there's no right way to do specifically that. A double[4][4]
array is not convertible to a double **
pointer. These are two alternative, incompatible ways to implement a 2D array. Something needs to be changed: either the function's interface, or the structure of the array passed as an argument.
不,没有正确的方法可以做到这一点。甲double[4][4]
阵列是无法转换为一个double **
指针。这是实现二维数组的两种替代的、不兼容的方法。需要改变一些东西:函数的接口,或者作为参数传递的数组的结构。
The simplest way to do the latter, i.e. to make your existing double[4][4]
array compatible with the function, is to create temporary "index" arrays of type double *[4]
pointing to the beginnings of each row in each matrix
执行后者的最简单方法,即使您现有的double[4][4]
数组与函数兼容,是创建double *[4]
指向每个矩阵中每一行开头的类型的临时“索引”数组
double *startRows[4] = { startMatrix[0], startMatrix[1], startMatrix[2] , startMatrix[3] };
double *inverseRows[4] = { /* same thing here */ };
and pass these "index" arrays instead
并传递这些“索引”数组
MatrixInversion(startRows, 4, inverseRows);
Once the function finished working, you can forget about the startRows
and inverseRows
arrays, since the result will be placed into your original inverseMatrix
array correctly.
一旦函数完成工作,您就可以忘记startRows
和inverseRows
数组,因为结果将正确放入原始inverseMatrix
数组中。
回答by UncleBens
For given reason that two-dimensional array (one contiguous block of memory) and an array of pointers (not contiguous) are very different things, you can't pass a two-dimensional array to a function working with pointer-to-pointer.
由于二维数组(一个连续的内存块)和指针数组(不连续)是非常不同的东西,因此您不能将二维数组传递给使用指针到指针的函数。
One thing you could do: templates. Make the size of the second dimension a template parameter.
你可以做的一件事:模板。将第二个维度的大小作为模板参数。
#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);
}
Another, a bit clumsier way might be to make the function accept a pointer to a single-dimensional array, and both width and height given as arguments, and calculate the indexes into a two-dimensional representation yourself.
另一种有点笨拙的方法可能是让函数接受一个指向一维数组的指针,并将宽度和高度作为参数给出,然后自己将索引计算为二维表示。
#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);
}
Naturally, a matrix is something that deserves a class of its own (but the above might still be relevant, if you need to write helper functions).
自然,矩阵值得拥有一个自己的类(但如果您需要编写辅助函数,上述内容可能仍然相关)。
回答by e.James
Since you are using C++, the proper way to do something like this would be with a custom class and some templates. The following example is rather rough, but it gets the basic point across.
由于您使用的是 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);
}
}
}
回答by leiz
Two dimensional array is not a pointer to pointer or something similar. The correct type for you startMatrix is double (*)[4]
. For your function, the signature should be like:
二维数组不是指向指针的指针或类似的东西。startMatrix 的正确类型是double (*)[4]
. 对于您的功能,签名应如下所示:
MatrixInversion( double (*A)[4], int order, double (*B)[4] );
回答by Cloud Cho
There is a solution using the pointer to point by bobobobo
有一个使用指针指向bobobobo的解决方案
William Sherif (bobobobo) used the C version and I just want to show C++ version of bobobobo's answer.
William Sherif (bobobobo) 使用了 C 版本,我只想展示 bobobobo 答案的 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) ];
}
The rest of code is the same with bobobobo's.
其余代码与 bobobobo 相同。
回答by trieck
You can definitely do something like the code below, if you want.
如果你愿意,你绝对可以像下面的代码那样做。
template <typename T, int n>
class MatrixP
{
public:
MatrixP operator()(T array[][n])
{
for (auto i = 0; i < n; ++i) {
v_[i] = &array[i][0];
}
return *this;
}
operator T**()
{
return v_;
}
private:
T* v_[n] = {};
};
void foo(int** pp, int m, int n)
{
for (auto i = 0; i < m; ++i) {
for (auto j = 0; j < n; ++j) {
std::cout << pp[i][j] << std::endl;
}
}
}
int main(int argc, char** argv)
{
int array[2][2] = { { 1, 2 }, { 3, 4 } };
auto pa = MatrixP<int, 2>()(array);
foo(pa, 2, 2);
}
回答by David
The problem is that a two-dimensional array is not the same as an array of pointers. A two-dimensional array stores the elements one row after another — so, when you pass such an array around, only a pointer to the start is given. The receiving function can work out how to find any element of the array, but only if it knows the length of each row.
问题在于二维数组与指针数组不同。二维数组一行一行地存储元素——因此,当你传递这样一个数组时,只会给出一个指向开始的指针。接收函数可以计算出如何找到数组的任何元素,但前提是它知道每一行的长度。
So, your receiving function should be declared as void MatrixInversion(double A[4][], int order, double B[4][])
.
因此,您的接收函数应声明为void MatrixInversion(double A[4][], int order, double B[4][])
.
回答by Test
by nice coding if c++:
通过很好的编码,如果 c++:
struct matrix {
double m[4][4];
};
matrix startMatrix;
matrix inverseMatrix;
so the interfacewould be
所以界面将是
void MatrixInversion(matrix &A, int order, matrix &B);
and use it
并使用它
MatrixInversion(startMatrix, 4, inverseMatrix);
The benefit
好处
- the interface is very simple and clear.
- once need to modify "m" of matrix internally, you don't need to update the interface.
- 界面非常简单明了。
- 一旦需要在内部修改矩阵的“m”,就不需要更新界面。
Or this way
或者这样
struct matrix {
void Inversion(matrix &inv, int order) {...}
protected:
double m[4][4];
};
matrix startMatrix;
matrix inverseMatrix;
...
An ugly way in c
c语言中的丑陋方式
void MatrixInversion(void *A, int order, void *B);
MatrixInversion((void*)startMatrix, 4, (void*)inverseMatrix);
EDIT: reference code for MatrixInversion which will not crash:
编辑: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);
}