1

我正在尝试在 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 的问题......但我只想知道我的分配例程不是问题。

4

2 回答 2

1

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

这让我认为,当 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]时,编译器会将其转换为((i*B + j)*C + k)*sizeof(double)arr. 这里不涉及中间指针,但编译器必须知道维度 B 和 C。

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

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

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

于 2010-10-26T09:20:55.243 回答
0

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

grid->x;

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

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

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

grid->x

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

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

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

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

于 2010-10-25T18:41:55.740 回答