C中的动态连续3D数组

时间:2010-10-25 16:43:37

标签: c multidimensional-array allocation netcdf

我正在尝试在C代码中实现动态分配的连续3D数组。数组必须是连续的,因为我依赖于数组的netCDF输出。现在我调整了这里发布的解决方案Stack OverFlow Solution。这适用于动态分配数组并索引它们...但是,当netCDF输出它们时,有一个偏移量,它似乎可以缩放为第二个索引大小(jcount)。这是修改后的功能:

void*** newarray(int icount, int jcount, int kcount, int type_size)
{
  int i,j,k;
  void*** iret = (void***)malloc(icount*sizeof(void***)+icount*jcount*sizeof(void**)+icount*jcount*kcount*type_size);
  void** jret = (void**)(iret+icount);
  char* kret = (char*)(jret+icount*jcount);
  for(i=0;i<icount;i++)
  {
    iret[i] = &jret[i*jcount];
  }
  for(i=0;i<icount;i++)
  {
    for(j=0;j<jcount;j++)
    {
      jret[i*jcount+j] = &kret[i*jcount*kcount*type_size+j*kcount*type_size];
    }
  }
  return iret;
}

如果我正确地理解了这个功能,我会为构成iret(第一个索引)的3D指针,构成jret(第二个索引)的2D指针和构成kret的实际值的空间分配空间。然后将2D jret指针与iret的2D阵列部分相关联。然后对于kret也是如此。然后iret的每个地址都指向jret每个部分的第一个值。然后jret的每个地址都指向kret的第一个地址。

对于记录,一切都正常,我的数组的预处理器定义值。另外,如果我在代码中使用一些printf语句来检查数组的数字,它们看起来都正确索引并且代码运行正常,那么输出似乎是数组的非连续内存存储的结果。 / p>

我有一个结构形式:

typedef struct
{
  double ***test;
} STRUCT_TYPE;

然后我使用

分配
mhd    = (STRUCT_TYPE *)  malloc(sizeof(STRUCT_TYPE));
mhd.test = (double***) newarray(101,7,101,sizeof(double));

这可能是netCDF的问题......但我只是想知道我的分配例程不是问题。

2 个答案:

答案 0 :(得分:1)

这实际上是对Lazer答案中问题的回答:

  

这让我觉得当C为数组分配内存时,它会分配使用的内存&gt;首先存储值,然后为提供的指针分配内存   结构到多维数组。

     

也许有人可以为我清除这个?

之间存在非常根本的差异
double arr[A][B][C];

double ***ptr;

尽管两者都可以使用x[i][j][k]编制索引,但生成的机器代码却非常不同。

double arr[A][B][C]是由C双打的B阵列组成的A阵列。在代码中将此索引编译为arr[i][j][k]时,编译器会将其转换为((i*B + j)*C + k)*sizeof(double)的起始arr字节的偏移量。这里没有涉及中间指针,但编译器必须知道维度B和C.

'double *** ptr'是指向(数组的开始)指针(指向数组的开头)double的指针(指向数组的开头)。在代码中将此索引编译为ptr[i][j][k]时,编译器别无选择,只能单独执行每个索引操作并遵循所有中间指针。这导致代码类似于

temp1 = ptr[i];
temp2 = temp1[j];
result = temp2[k];

newarray函数从单个内存块中雕刻出所有这些组件数组,但语言并不需要这样,并且编译器不知道发生这种情况,所以它必须将所有组件阵列视为彼此完全独立。

答案 1 :(得分:0)

嗯,我找到了一个解决方案......虽然它更像是一种惯例。当我最初设计我的代码时,我只是使用预处理器指令来声明我的数组大小。然后我简单地在结构中声明每个数组。为了节省内存,我只是将指向结构的指针传递给了我的子函数。这意味着如果我要引用main()例程之外的元素,我会使用类似的东西:

grid->x;

现在,我引用x的每个元素,如

grid->x[i][j][k];

当然,当netCDF函数需要一个指向它要存储的变量的指针时,我只是传递了它

grid->x

然而,使用这个新的内存分配函数,当我将它传递给一个函数时,我实际上传递了为各种指针留出的内存空间的第一个地址。本质上,我将指针传递给内存中的错误地址。我所要做的就是将传递的参数更改为:

&grid->x[0][0][0]

我得到了正确的数组输出。这让我觉得当C为数组分配内存时,它首先分配用于存储值的内存,然后为指针分配内存,为多维数组提供结构。

也许有人可以为我清除这个?