如何将指针视为多数组?

时间:2010-01-29 12:58:14

标签: c++ c

我有这个循环,给出了seg。故障。

  s->c = malloc(width * height * sizeof(double));
  if (s->c == NULL) { puts("malloc failed"); exit(1); }

  for (int n = 0; n < width; n++) {
    for (int m = 0; m < height; m++) {

      d = (&s->c)[m][n];

      printf("d %f\n", d);
      printf("m %i\n", m);
      printf("n %i\n", n);

    }
  }

内部s-&gt; c是:

double* c;

执行时只输出:

d 27.000000
m 0
n 0

然后是seg。故障。

当我将s-&gt; c视为一维数组时,它有效,但我真的希望将其视为二维数组。

当c指针在结构中时,这可能吗?

如果是,(&s->c)[m][n]是否正确访问元素?

桑德拉

7 个答案:

答案 0 :(得分:5)

问题是编译器不知道矩阵的维数。

如果您有double tab[m][n],则可以tab[row][col]

访问元素*(tab + (row * n) + col)

在您的情况下,您只有double *tab;可以被视为指向元素tab[0][0]的指针,没有关于矩阵维度的信息,编译器无法计算正确的地址。

您可以自己计算地址(例如使用宏)但会丢失漂亮的tab[x][y]语法。

我很惊讶它编译。您应该至少收到一条关于隐式地向指针投射双精度的警告。

答案 1 :(得分:4)

我很惊讶它甚至编译。显然cdouble*,因此(&s->c)[m]是m double。现在,double没有operator[],因此我看不到[n](&s->c)[m][n]部分的合法性。

据推测,您已经以不同方式宣布c。有不同的解决方案:指向指针的指针,指向双精度数组的指针,指向双精度的指针数组等。如果分配与声明匹配,则所有可能都有效。在您的情况下,分配将与声明不匹配。

答案 2 :(得分:2)

访问数组元素的正确方法是

d = s->c[m * width + n];

这就是将它视为一维数组的意思吗?

答案 3 :(得分:1)

使用

访问元素
double d = s->c[m*width+n];

也许通过内联函数,以避免意外行为。

编译器不知道您想要的2D数组的宽度。它可能将(&amp; s-&gt; c)[m] [n]解释为s-> c [m + n],或者作为完全不同的东西。

答案 4 :(得分:1)

简短回答:您不能将其视为2D数组,至少不是您期望的方式。

写作的原因

(&s->c)[m][n]

不起作用可以如下所示。假设s->c的地址是0x00080004,s->c指向的动态分配的内存的地址是0x00001000。

  1. 表达式(&s->c)[m][n]评估为*(*(&s->c + m) + n);
  2. 表达式&s->c的计算结果为0x00080004;
  3. 表达式(&s->c + m)的计算结果为0x00080004+m;
  4. 表达式*(&s->c + m)计算0x00080004+m指向的值的值。如果m为0,则0x00080004+m指向0x00001000,这是您动态分配的内存的地址(*(&x) == x)。如果m是任何其他值,则0x00080004+m随机指向某处;
  5. 表达式(*(&s->c + m) + n)评估为0x00080004+m个点,以n计算。如果m为0,则值为0x00001000+n,或者是动态分配的内存的偏移量。如果m不为0,那么该值是随机的;
  6. 表达式*(*(&s->c) + m) + n)尝试取消引用上述值。如果m为0,则结果是动态分配的数组中元素的值。如果m不为0,则结果为......其他内容。在你的情况下,一个段错误。
  7. 如果要动态分配2D数组,则必须使用指向指针的指针并按步骤分配,如下所示:

    struct {
      ...
      double **c;
      ...
    } *s;
    ...
    /**
     * Notes:  type of s->c is double **
     *         type of *(s->c) and s->c[i] is double *
     *         type of *(s->c[i]) and s->c[i][j] is double
     */
    s->c = malloc(sizeof *(s->c) * rows); 
    if (s->c)
    {
      for (i = 0; i < rows; i++)
      {
        s->c[i] = malloc(sizeof *(s->c[i]) * columns);
        if (s->c[i])
        {
          // initialize s->c[i][0] through s->c[i][columns-1]
        }
      }
    }
    

答案 5 :(得分:0)

如果您想将s-&gt; c作为一维数组分配,那么您可以定义一个为您完成工作的宏(但您需要知道第二个维度):

#define AR(M, X, Y) ((M)[(Y) + dimy * (X)])

答案 6 :(得分:0)

我很惊讶没有人提到boost::multi_array_ref

#include <iostream>
#include <boost/multi_array.hpp>

int main()
{
    int rows = 4, cols = 3;

    // Allocate one big block of contiguous data for entire multi-array
    double* arrayData = new double[rows*cols];

    if (arrayData)
    {
        boost::multi_array_ref<double, 2>
             arrayRef(arrayData, boost::extents[rows][cols]);
        for (int row = 0; row < rows; ++row)
        {
            for (int col = 0; col < cols; ++col)
            {
                arrayRef[row][col] = row*cols + col;
                std::cout << arrayRef[row][col] << " ";
            }
            std::cout << std::endl;
        }
    }
    delete [] arrayData;
}

您也可以使用boost :: multi_array并动态调整大小:

boost::multi_array_ref<double, 2> marray;
marray.resize(boost::extents[rows][cols]);