为什么我在C中的多维动态分配不起作用?

为什么我在C中的多维动态分配不起作用?,c,arrays,pointers,indirection,C,Arrays,Pointers,Indirection,我一直在努力解决C语言中多维动态分配数组的分配和使用问题。我非常感谢您的帮助 我试过两种方法。第一: cdr = (double ***) malloc(NUM_REGIONS * sizeof(double **)); for(i=0; i<NUM_REGIONS; i++){ cdr[i] = (double **) malloc(numRatings * sizeof(double *)); for(j=0; j<numRatings; j++){ c

我一直在努力解决C语言中多维动态分配数组的分配和使用问题。我非常感谢您的帮助

我试过两种方法。第一:

cdr = (double ***) malloc(NUM_REGIONS * sizeof(double **));
for(i=0; i<NUM_REGIONS; i++){
   cdr[i] = (double **) malloc(numRatings * sizeof(double *));
   for(j=0; j<numRatings; j++){
       cdr[i][j] = (double *) malloc(remQuarters * sizeof(double));
   }
}  
cdr=(double***)malloc(NUM_REGIONS*sizeof(double**));

对于(i=0;i我花了很长时间才弄清楚你到底看到了什么问题

我尝试了以下多维双精度数组,没有问题:

int i, j;
int rows = 5;
int columns = 10;
int z_axis = 5;
double ***cdr = malloc(rows * sizeof(double **));
for (i = 0; i < rows; i++)
{
  cdr[i] = malloc(columns * sizeof(double *));
  for (j = 0; j < columns; j++)
  {
    cdr[i][j] = malloc(z_axis * sizeof(double));
  }
}
inti,j;
int行=5;
int列=10;
int z_轴=5;
double***cdr=malloc(行*sizeof(double**));
对于(i=0;i

有关此问题的详细信息,请参阅c-faq:

很久以前,在大学里,我得出结论,c中的多维数组应该用1D数组模拟。首先需要分配一个足够大的缓冲区来容纳所有元素。对于一个2D数组,应该是
ncolumns*nrows*sizeof(element)
。然后通过将多维索引转换为一维索引来访问数组元素。对于二维数组,访问(i,j)转换为
bufA[i*ncolumns+j]

问题在于取消引用。
cdr[i][j]
不会执行您想要的操作。分配
cdr[i]
,您将指针放在该索引上。但是,
cdr[i][j]
不会取消引用
cdr[i]
。它假定您有一个矩形内存块,并向cdr添加适当的值以确定
cdr[i][j]的位置
仍然存在。您可能必须使用
*
s手动取消引用。

什么是
cdr
应该是什么?一个三维double数组(这是我根据您的代码片段假设的)?指向double的二维指针数组?还是指向二维double数组的指针

假设第一个:

#include <stdlib.h>

int main(void)
{
  double ***cdr = malloc(sizeof *cdr * NUM_REGIONS);
  if (cdr)
  {
    size_t i;
    for (i = 0; i < NUM_REGIONS; i++)
    {
      cdr[i] = malloc(sizeof *cdr[i] * numRatings);
      if (cdr[i])
      {
        cdr[i][j] = malloc(sizeof *cdr[i][j] * remQuarters);
      }
    }
  }
  return 0;
}

事实证明,编写的代码是有效的(尽管正如一些人指出的,它确实有改进风格的空间)。我跟踪了代码中的实际问题,找到了一些文件输入,这些文件输入对于缓冲区来说太大(这对我来说是错误检查的一个教训)


调试器给出了一些奇怪的输出,让我专注于代码的这一部分。我仍然不明白为什么我的调试器在别人不这么做的情况下却在这么做,但我改天再处理。

我尝试了你的第一个代码片段。它与我一起工作。和cdr[I]每次都是一个新位置,没有任何问题。我的猜测是:您的numRatings变量等于0或uninitialized@stacker,cdr声明为double***cdr;声明中还有一些其他变量,但这不重要,对吗?@Ben,numRatings等于27。在调试器中显示良好。@标记,因为它声明为***指针编译器无法找出第一个索引的行有多大,因此ssegiv答案是正确的。你确定这不能正常工作吗?你看到了什么地址?你确定地址完全相同吗?你的第一种方法似乎是有效的,我的测试证实了这一点。我一直在使用这种技术在这个例子中,
cdr[i][j]!=cdr[i*rowlen+j]
。在这个问题中,
cdr
具有type
double***
。这使得
cdr[i]
具有type
double**
cdr[i][j]
使用type
double*
。语法是正确的。我确实想到了这一点,可能就是我最终的想法。我只是认为数组表示法更容易阅读和理解。但我想这只有在它起作用的情况下才有意义!我可以看到更多的上下文会有所帮助。我不清楚double的3D数组与p的2D数组有何不同指向double的指针。我试图获取两者的特征。最终,我试图将
cdr[region][rating]
作为指向double的指针发送到一个函数。该函数将
double*cdr1
作为参数,然后作为
cdr1[I]循环所有remquarters值
。这有意义吗?另外,感谢大家的“良好管理”说明。是的,这是有意义的。您可以通过简单地将cdr声明为3D VLA(如果您有C99编译器可用;如果没有,您将陷入分段分配的困境)来减轻自己的痛苦。请记住,数组表达式的类型从“T的M元素数组”在大多数上下文中都是“指向T的指针”。如果将
cdr
声明为3D数组,例如
double-cdr[X][Y][Z];
,则表达式的类型
cdr[i][j]
是“double的Z元素数组”,但当您将其传递给函数时,它将“衰减”为类型“指向double的指针”
int i, j;
int rows = 5;
int columns = 10;
int z_axis = 5;
double ***cdr = malloc(rows * sizeof(double **));
for (i = 0; i < rows; i++)
{
  cdr[i] = malloc(columns * sizeof(double *));
  for (j = 0; j < columns; j++)
  {
    cdr[i][j] = malloc(z_axis * sizeof(double));
  }
}
#include <stdlib.h>

int main(void)
{
  double ***cdr = malloc(sizeof *cdr * NUM_REGIONS);
  if (cdr)
  {
    size_t i;
    for (i = 0; i < NUM_REGIONS; i++)
    {
      cdr[i] = malloc(sizeof *cdr[i] * numRatings);
      if (cdr[i])
      {
        cdr[i][j] = malloc(sizeof *cdr[i][j] * remQuarters);
      }
    }
  }
  return 0;
}
double cdr[NUM_REGIONS][numRatings][remQuarters];