C ++铸造静态二维双数组加倍**

时间:2013-04-02 14:13:29

标签: 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 = &m[0][0];
double **c = &b;

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

double m[3][4]数组投射到double**类型的正确方法是什么?

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

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

它与动态分配的数组一起工作正常。我怀疑只有它的工作方式是分配新的动态数组并将原始静态数组复制一个元素......

6 个答案:

答案 0 :(得分:14)

你不能。

符号double**指的是指针数组。你没有一个指针数组,你有一组双打数组。

答案 1 :(得分: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);

答案 2 :(得分: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的类型 是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

正如其他人所说,double**是一种不同的类型 它的尺寸。要将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*的{​​{1}}。然后,在m[0]中, _m + 4被转换为指向_m的{​​{1}}和指针 它已添加double*。因此,m[0]是第四个跟随的指针 4_m + 4等等。

到目前为止,我已经解释了为什么你不能将_m[0](或任何其他尺寸)投射到_m[4]。现在,我会在您的特定情况下显示如何定义计算。

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

答案 3 :(得分: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);

答案 4 :(得分:0)

您可以将2d数组作为函数参数传递:

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

答案 5 :(得分:0)

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

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