【问题标题】:Dynamic Contiguous 3D arrays in CC中的动态连续3D数组
【发布时间】:2010-10-25 16:43:37
【问题描述】:

我正在尝试在 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 被分配空间给组成 iret(第一个索引)的 3D 指针、组成 jret(第二个索引)的 2D 指针和组成 kret 的实际值的空间。二维 jret 指针随后与 iret 的二维数组部分相关联。然后对 kret 进行同样的操作。然后 iret 的每个地址都指向 jret 的每个部分的第一个值。那么jret的每一个地址都指向kret的首地址。

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

我的结构如下:

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

然后我分配使用

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

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

【问题讨论】:

    标签: c multidimensional-array allocation netcdf


    【解决方案1】:

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

    这让我认为,当 C 为数组分配内存时,它会先分配使用的内存 > 来存储值,然后再为提供的指针分配内存 结构到多维数组。

    也许有人可以帮我解决这个问题?

    C 和 C 之间有一个非常根本的区别

    double arr[A][B][C];
    

    double ***ptr;
    

    虽然两者都可以使用x[i][j][k] 进行索引,但生成的机器代码却大不相同。

    double arr[A][B][C] 是 A 数组 B 数组 C 双精度数组。当在代码中将其索引为arr[i][j][k] 时,编译器将其转换为从arr 开始的((i*B + j)*C + k)*sizeof(double) 字节的偏移量。这里不涉及中间指针,但是编译器必须知道维度 B 和 C。

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

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

    newarray 函数将所有这些组件数组从单个内存块中分割出来,但这不是语言所要求的,编译器也不知道这正在发生,因此它必须处理所有组件数组彼此完全独立。

    【讨论】:

    • 感谢您解决这个问题。奇怪的是,将数组写入 netCDF 文件的函数需要连续的内存块。
    【解决方案2】:

    好吧,我找到了解决办法……尽管这更像是一种约定俗成的事情。当我最初设计我的代码时,我只是使用预处理器指令来声明我的数组大小。然后我简单地在结构中声明了每个数组。为了节省内存,我只是将一个指向结构的指针传递给我的子函数。这意味着如果我要引用 main() 例程之外的元素,我会使用如下内容:

    grid->x;
    

    现在我和 x 一样引用每个元素

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

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

    grid->x
    

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

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

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

    也许有人可以帮我解决这个问题?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-22
      • 2016-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-05
      • 2016-04-09
      相关资源
      最近更新 更多