不是double [] []相当于** double?

时间:2013-10-28 14:01:59

标签: c++ pointers matrix multidimensional-array

我问这个是因为我的程序有两个函数来乘法矩阵,它们只乘以4x4和4x1矩阵。标题是:

 double** mult4x1(double **m1, double **m2);
 double** mult4x4(double **m1, double **m2);

他们做m1 * m2并以**双返回,下面是4x4乘法的片段。

 double** mult4x4(double **m1, double **m2){
      double** result = (double**) malloc(sizeof(double)*4);
      for (int i = 0; i < 4; i++) {
           result[i] = (double*) malloc(sizeof(double)*4);
      }
      ...multiply...
      return result;
 }

mult4x1和mult4x4之间的区别仅在于它们内部使用的索引。

我有这3个矩阵:

double m1[4][4] = {
    {2, 3, 5, 6},
    {9, 8, 1, 7},
    {5, 4, 3, 1},
    {7, 6, 1, 2}
};

double m2[4][4] = {
    {1, 0, 0, 0},
    {0, 1, 0, 0},
    {0, 0, 1, 0},
    {0, 0, 0, 1}
};

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

尝试将这些矩阵相乘,发生错误。

double** test = mult4x4(m1, m2);
double** test2 = mult4x1(identity4x4(), m3);
//identity4x4() creates a 4x4 identity matrix - double** identity4x4();

收率:

  

错误:无法转换double (*)[4]' to double * '参数1' to double * mult4x4(double * ,double *)'

     

错误:无法转换double (*)[1]' to double * '参数2' to double * mult4x1(double * ,double *)'

不是double [] []应该等于** double吗?一个double数组的数组。 任何澄清,误解和错误都是受欢迎的。

9 个答案:

答案 0 :(得分:51)

没有。
double**是指向双精度(double*)的指针。

所以实际上它应该像这样创建(注意第一个malloc sizeof()中的额外*):

  double** result = (double**) malloc(sizeof(double*)*4);
  for (int i = 0; i < 4; i++) {
       result[i] = (double*) malloc(sizeof(double)*4);
  }

所以在内存中它看起来像这样:

[] -> { d,d,d,d }
[] -> { d,d,d,d }
[] -> { d,d,d,d }
[] -> { d,d,d,d }

有4个缓冲区可容纳4个双打,但不是连续的。

虽然你的双[4] [4]是内存中的连续缓冲区,但是这样:

 { { d,d,d,d } { d,d,d,d } {d,d,d,d} {d,d,d,d} }

答案 1 :(得分:24)

尽管double[N][M]double**都允许你处理2D数组,但两者绝对不相同:前者代表double s的2D数组,而后者代表指针指向double的指针,可以解释(借助方便的C / C ++方括号语法)作为指向double的指针数组,或作为{的数组数组{1}}。

double代表“矩形”形状的2D数组,而double[N][M]则允许您通过为矩阵的每一行分配不同数量的内存来构建“自由形式”(锯齿状)数组。 / p>

与编译器的区别在于给定double**和一对整数double[N][M],它可以通过计算数组原点的偏移量来计算元素的位置,而无需读取任何内容。记忆。但是,给定{r,c},编译器必须计算指向行的指针的地址,读取该指针,然后才计算目标元素的地址。由于这种差异,这两者是不可互换的。

答案 2 :(得分:3)

没有类型[][]。你所拥有的实际上是m2,它是一个大小为4的数组的数组,类型为double,m1是一个大小为1的数组数组。大小为4的数组数组不等于双指针。

答案 3 :(得分:2)

好吧,我希望我不会在这里变成愚蠢的,但是当您处理连续的内存块时,也会使用符号double [][],而double**不一定是连续的。

我认为这就是错误背后的原因。即使您可以使用相同的语义来访问值,它们实际上也是不同的类型。

答案 4 :(得分:2)

[] []不等于**; double ** var;是一个指针指针,你可以从你在内存中的分配看到你持有一个指针数组,每个指针指向一个值为double的数组

double var [4][4];在内存中保存,有点相当于double *;在这种情况下,知道矩阵的大小(4 x 4),所以当你使用var[2][2]时,它知道它在内存中的位置; var[x][y]转换为以下内容:var[x + y * 4],声明可以解释为double var [16];

Raxvan。

答案 5 :(得分:2)

不,不是。 double[n][m]为你的二维数组分配一个足够大的内存块。然后,您可以方便地无需计算自己的索引。将二维数组传递给函数时,编译器要求您给出内部维度的大小,以便它可以计算出索引。

double**是指向指针的指针。由于C允许指针算术,它可能意味着一个指针数组,其中每个指针指向一个双精度数组。值本身不需要驻留在连续的内存块中。你可以看到他们是完全不同的野兽。

如果您有double[n][m]并希望将其传递给double **,则需要构建自己的索引数组。

答案 6 :(得分:2)

否...... m1是一个包含四个元素的数组,每个元素都是一个包含四个元素的数组。与m2相同。即使第一个“级别”从一个数组衰减到一个指针,第二个“级别”也不会。问题是为什么?我们来看一些代码:

/* double[4][4] implicitly converts to double(*)[4]
 * giving you a pointer to first element of m1 so
 * you get back an array of four doubles.
 */
double (*pm1a)[4] = m1[0];

/* This isn't right, but let's pretend that it was
 * and that what you got back was a pointer
 * to a pointer that pointed to m1 properly.
 */
double **pm1b = (double **)m1[0];

那么,如果我们要做pm1a[1]pm1b[1],我们的假设代码会发生什么?

pm1a[1]没问题:它会正确地提前pm1a 4 * sizeof(double)(因为指针指向double[4])。

另一方面,

pm1b[1]会破坏:它会以错误的数量前进:指向双精度的指针的大小。

但这不是全部。还有一个更微妙的错误。如果两个维度都要衰减,则编译器无法知道正在访问数组。它会很高兴地将pm1b[1]解释为指针到double。然后会发生什么?它将在该位置存储double ,并将其作为指针视为double

你可以看出为什么这会是一场灾难。

答案 7 :(得分:1)

另一个不同之处在于,如果将其声明为double [] [](最终字段之类的东西),则不能将double指向任何其他内存地址

但是如果你将它声明为**,那么它可以指向任何内存位置。

答案 8 :(得分:1)

不,它们肯定不是等价的,前者表示二维的二维数组,而后者表示指向双精度的指针。