9

我的程序中有这样的矩阵:

double m[3][4] = 
    {
        {2, 4, 5, 7},
        {4, 5, 1, 12},
        {9, 12, 13, -4}
    };

而且我想将其转换为double**类型。

我已经尝试过 simple double** a = (double**)m;,但它不起作用(当我尝试读取任何值时,我得到“访问冲突读取位置 0x00000000。”,这意味着我正在尝试从NULL地址读取。

我找到了几乎可行的解决方案:

double *b = &m[0][0];
double **c = &b;

当我读取字段时它可以工作c[0][any] 但是当我尝试从字段读取值时,会出现相同的 NULL 地址读取问题c[1][0]

将我的double m[3][4]数组转换为 type的正确方法是什么double**

编辑:你说那是不可能的。所以我会稍微改变一个问题。如何将二维双精度数组作为参数传递给函数?我的函数有原型:

void calculate(double **matrix, int n); //where matrix size is always n by n+1 

它适用于动态分配的数组。我怀疑使其工作的唯一方法是分配新的动态数组并一个接一个地复制原始静态数组......

4

6 回答 6

14

你不能。

该符号double**是指一个指针数组。你没有一个指针数组,你有一个双精度数组。

于 2013-04-02T14:16:18.560 回答
9

您不能只转换数组。你将不得不创建这样的东西:

double m[3][4] = 
    {
        {2, 4, 5, 7},
        {4, 5, 1, 12},
        {9, 12, 13, -4}
    };

double *marray[3] = {m[0],m[1],m[2]};
calculate(marray,3);

或者您可以使用循环:

const size_t n = 3;
double *marray[n];
for (size_t i=0; i!=n; ++i) {
    marray[i] = m[i];
}
calculate(marray,n);
于 2013-04-02T14:20:24.650 回答
7

当你写

double m[3][4] 
    {
        {2, 4, 5, 7},
        {4, 5, 1, 12},
        {9, 12, 13, -4}
    };

编译器实际上创建了一个双精度数组,就像您编写的一样

double _m[] = {2, 4, 5, 7, 4, 5, 1, 12, 9, 12, 13, -4};

但是,由于 C/C++ 类型系统,编译器记住m's 的类型是double [3][4]. 特别是它记得大小 3 和 4。

当你写

m[i][j]

编译器将其替换为

_m[i * 4 + j];

4来自 中的第二个大小double [3][4]。)例如, m[1][2] == 1以及_m[1 * 4 + 2] == _m[6] == 1

正如其他人所说, adouble**是一种不同的类型,它不携带尺寸。要考虑double** a为 3 x 4 矩阵,a[0]a[1]必须 a[2]是指向double(即double*)指向相应行的第一个元素的指针。你可以用

double* rows[] = { &m[0][0], &m[1][0], &m[2][0] };
double** a = &rows[0];

一个简单的演员表不会创建rows上面的变量。让我介绍其他替代(但等效)的方法来定义rows

double* rows[] = { &m[0][0], &m[0][0] + 4, &m[0][0] + 2 * 4};
double* rows[] = { &_m[0], &_m[4], &_m[2 * 4]};

如您所见,只需要第二种尺寸(即4)。通常,对于多维数组,除了第一个之外的所有大小都是必需的。因此,一维数组

double x[4] = { 1, 2, 3, 4 };

可以隐式转换为double*

double* y = x;

利用这个事实,我们也可以写

double* rows[] = { _m, _m + 4, _m + 2 * 4};

事实上,_m被转换为double*指向m[0]。然后, in _m + 4_mis 被转换为double*指向m[0]并添加到 this 的指针4。因此,_m + 4是第四个 double 之后的指针 _m[0]_m[4]以此类推。

到目前为止,我已经解释了为什么不能将 a double [3][4](或任何其他大小)转换为double**. 现在,我将在您的特定情况下展示如何定义计算。

template <int N>
void calculate(double (&m)[N][N+1]) {
   // use m as a double[N][N+1]
}

你打电话

calculate(m);

编译器会为你推导出大小N。一般来说(即,当第二维不是 时N + 1)你可以写

template <int N, int M>
void calculate(double (&m)[N][M]) {
   // use m as a double[N][M]
}
于 2013-04-02T15:08:06.073 回答
2

如果您总是使用数组(无指针)进行初始化,并且您能够避免在计算函数中使用指针,您可以考虑使用以下选项,它使用模板的大小扣除。

template<int m, int n>
void doubleFunc(double (&mat)[m][n])
{
    for (auto i = 0; i < m; i++)
    {
        for (auto j = 0; j < n; j++)
        {
            std::cout << mat[i][j] << std::endl;
        }
    }
}

它在我的快速测试期间有效。

double m[3][4] = 
{
    {2, 4, 5, 7},
    {4, 5, 1, 12},
    {9, 12, 13, -4}
};

doubleFunc(m);
于 2013-04-02T14:59:58.413 回答
0

您可以将二维数组作为函数参数传递:

void calculate(double matrix[][y], int n);

于 2013-04-02T14:32:29.433 回答
0

在 C++ 标准中采用可变长度数组之前,您的选择包括:

  • 如果您的编译器支持可变长度数组作为扩展,您可能可以使用函数声明来传递它们,例如void foo(std::size_t n, double a[][n+1]). 请注意,编译器可能需要在使用或需要某些特殊语法n的参数声明之前传递。n
  • 您可以在函数中手动传递 adouble *并进行索引运算:void foo(std::size_t n, double *a) { … a[row*(n+1) + column] … }
  • 您可以通过在其访问器函数中执行索引算术来创建一个实现可变长度数组的类。
  • n您可以为指向的指针分配空间,double用指向数组每一行的指针填充这些指针,并传递空间的地址。
于 2013-04-02T14:54:31.760 回答