C++ C++;将静态二维双数组转换为双数组**

C++ C++;将静态二维双数组转换为双数组**,c++,pointers,casting,double,C++,Pointers,Casting,Double,我的程序中有这样的矩阵: double m[3][4] = { {2, 4, 5, 7}, {4, 5, 1, 12}, {9, 12, 13, -4} }; 我想将其转换为double**类型 我已经试过简单的double**a=(double**)m,但它不起作用(当我尝试读取任何值时,我会得到“访问冲突读取位置0x00000000.”,这意味着我正在尝试从NULL地址读取 我找到了几乎可行的解决方案: double *b

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

double m[3][4] = 
    {
        {2, 4, 5, 7},
        {4, 5, 1, 12},
        {9, 12, 13, -4}
    };
我想将其转换为
double**
类型

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

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

double *b = &m[0][0];
double **c = &b;
当我读取字段
c[0][any]
但当我尝试从字段
c[1][0]
读取值时,同样的空地址读取问题也会出现

将我的
双m[3][4]
数组强制转换为键入
双**
的正确方法是什么

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

void calculate(double **matrix, int n); //where matrix size is always n by n+1 
它在动态分配的数组中运行良好。我怀疑唯一可行的方法是分配新的动态数组并将原始静态数组一个一个地复制…

你不能


表示法
double**
指的是一个指针数组。你没有指针数组,你有一个double数组。

你不能只强制转换数组。你必须创建如下内容:

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);

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


<> >代码>空格计算(双矩阵[][y],int n);

< P>直到变长数组在C++标准中,您的选择包括:

  • 如果您的编译器支持将可变长度数组作为扩展,则可以通过函数声明传递它们,例如
    void foo(std::size\t n,double a[][n+1])
    。请注意,编译器可能需要在使用
    n
    的参数声明之前传递
    n
    ,或者需要一些特殊语法
  • 您可以在函数中传递一个
    double*
    并手动执行索引算法:
    void foo(std::size\t n,double*a){…a[行*(n+1)+列]…}
  • 通过在其访问器函数中执行索引算法,可以创建一个实现可变长度数组的类
  • 您可以为
    n
    指向
    double
    的指针分配空间,用指向数组每一行的指针填充这些指针,并传递空间的地址

如果你总是使用数组(没有指针)进行初始化,并且你可以避免计算函数中的指针,那么你可以考虑下面的选项,它使用模板的大小推断。

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}
    };
m[i][j]
编译器实际上创建了一个双精度数组,就好像您编写了

double _m[] = {2, 4, 5, 7, 4, 5, 1, 12, 9, 12, 13, -4};
然而,多亏了C/C++类型系统,编译器记住了
m
的类型 是
双[3][4]
。它特别记得3号和4号

当你写作时

double m[3][4] 
    {
        {2, 4, 5, 7},
        {4, 5, 1, 12},
        {9, 12, 13, -4}
    };
m[i][j]
编译器将其替换为

_m[i * 4 + j];
(例如,
4
来自
double[3][4]
中的第二个大小),
m[1][2]==1
\u m[1*4+2]===1

正如其他人所说的那样,
double**
是一种不同的类型,它不携带 将其视为<代码>双** < /代码>作为3×4矩阵,<代码> A[ 0 ] < /代码>,<代码> A[ 1 ] < /代码>
a[2]
必须是指向指向 对应行的第一个元素。可以使用

double* rows[] = { &m[0][0], &m[1][0], &m[2][0] };
double** a = &rows[0];
简单的强制转换不会创建上面的变量
。让我来介绍其他变量 定义
行的替代(但等效)方法

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};
实际上,
\u m
被转换为指向
m[0]
double*
。然后,在
\u m+4
中,
\u m
被转换为指向
m[0]
和该指针的
double*
它添加了
4
。因此,
\u m+4
是后面第四个双精度指针
\u m[0]
,即
\u m[4]
,依此类推

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

template <int N>
void calculate(double (&m)[N][N+1]) {
   // use m as a double[N][N+1]
}
编译器将为您推断大小
N
。通常(即,当第二维不是
N+1
)您可以编写

template <int N, int M>
void calculate(double (&m)[N][M]) {
   // use m as a double[N][M]
}
模板
无效计算(双(&m)[N][m]){
//使用m作为双精度[N][m]
}

Casting不起作用。一个
double**
需要一个指向double的指针,而这不是您所拥有的。您可能可以使用
double*
并显式地传递数组维度。数组数组和指向指针的指针不是一回事。内存中的布局不是ma使用沃恩·卡托(Vaughn Cato)提出的技术。如果需要一个
double**
,你需要给它一个
double**
,而不是一个二维数组。你的
calculate
函数需要一个指向数组的指针。你的问题是你没有这个指针。你的解决办法是创建它。阅读Vaughn Cato的答案。这在我的情况下不起作用。数组可能有大小,例如100x100。我不会写
{m[0],m[1],m[2],…,m[99]};
在我的代码中:)@Gogowitchzak:在这种情况下,你可以使用一个循环(答案已更新)。它不是那么简单。我假设
array
可能有编译时未知的不同大小,也就是说,
n
不是编译时常量。因此,必须动态分配
marray
。哪种可能