简体   繁体   English

C中的动态连续3D阵列

[英]Dynamic Contiguous 3D arrays in C

I'm trying to implement dynamically allocated contiguous 3D arrays in a C code. 我正在尝试在C代码中实现动态分配的连续3D数组。 The arrays must be contiguous because I'm relying on netCDF output of the arrays. 数组必须是连续的,因为我依赖于数组的netCDF输出。 Now I adapted a solution posted here Stack OverFlow Solution . 现在,我修改了此处发布的解决方案Stack OverFlow Solution This works fine for dynamically allocating the arrays and indexing them...however, when netCDF outputs them there is an offset which appears to scale as the 2nd index size (jcount). 这对于动态分配数组并为它们建立索引非常有效……但是,当netCDF输出它们时,存在一个偏移量,该偏移量看起来像是第二个索引大小(jcount)一样。 Here is the modified function: 这是修改后的函数:

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;
}

If I understand this function correctly iret is allocated space for the 3D pointers composing iret (first index), the 2D pointers composing jret (2nd index) and the space for the actual values composing kret. 如果我正确理解此功能,则会为iret分配用于构成iret的3D指针(第一索引),用于构成jret的2D指针(第二索引)和用于构成kret的实际值的空间。 The 2D jret pointer is then associated with the 2D array section of iret. 然后将2D jret指针与iret的2D数组部分关联。 Then the same is done for kret. 然后对kret做同样的事情。 Then every address of iret is pointed to the first value of each section of jret. 然后,iret的每个地址都指向jret的每个部分的第一个值。 Then each address of jret is pointed to the first address of kret. 然后,将jret的每个地址指向kret的第一个地址。

For the record, everything was working fine with preprocessor defined values for my arrays. 记录下来,我的数组在预处理器定义的值下一切正常。 Also, if I use some printf statements in the code to check the numerics of the arrays they all appear to index correctly and the code runs correctly, it's just the output seems to be the result of non-contiguous memory storage of the arrays. 另外,如果我在代码中使用一些printf语句来检查它们都正确索引的数组的数字,并且代码正确运行,则只是输出似乎是数组的非连续内存存储的结果。

I have a structure of the form: 我有一个形式的结构:

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

Which I then allocate using 然后我使用分配

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

This may be an issue with netCDF...but I'd just like to know my allocation routine isn't the issue. 这可能是netCDF的问题...但是我只想知道我的分配例程不是问题。

This is actually an answer to the question in Lazer's answer: 这实际上是对Lazer答案中问题的答案:

This makes me think that when C allocates memory for an array it allocates the memory used > to store the values first then it allocates the memory for the pointers which provide structure to the multidimensional array. 这使我认为,当C为数组分配内存时,它首先分配用于存储值的内存,然后再为为多维数组提供结构的指针分配内存。

Maybe someone can clear this one up for me? 也许有人可以帮我解决这个问题?

There is a very fundamental difference in C between C之间存在非常根本的差异

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

and

double ***ptr;

Although both can be indexed with x[i][j][k] , the resulting machine code is very different. 尽管两者都可以用x[i][j][k]进行索引,但是生成的机器代码却大不相同。

double arr[A][B][C] is an array of A arrays of B arrays of C doubles. double arr[A][B][C]是C个double的B个数组的A个数组的数组。 When indexing this in the code as arr[i][j][k] , the compiler translates that to an offset of ((i*B + j)*C + k)*sizeof(double) bytes from the start of arr . 在代码中将其索引为arr[i][j][k] ,编译器会将其转换为从arr开头的((i*B + j)*C + k)*sizeof(double)个字节的偏移量。 There are no intermediate pointers involved here, but the dimensions B and C must be known to the compiler. 这里没有涉及中间指针,但是编译器必须知道维B和C。

'double ***ptr' is a pointer to (the start of an array of) pointers to (the start of an array of) pointers to (the start of an array of) double. 'double *** ptr'是指向double的指针(数组的起点)的指针(数组的起点)。 When indexing this in the code as ptr[i][j][k] , the compiler has no choice but to do each indexing operation separately and follow all the intermediate pointers. 当在代码中将其索引为ptr[i][j][k] ,编译器别无选择,只能分别执行每个索引操作并遵循所有中间指针。 This results in code similar to 这导致代码类似于

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

The newarray function carves all these component-arrays out of a single block of memory, but that is not required by the language and the compiler does not have the knowledge that this is taking place, so it has to treat all the component-arrays as being completely independent of each other. newarray函数将所有这些组件数组从单个内存块中剔除,但这不是语言所必需的,并且编译器不知道这种情况正在发生,因此必须将所有组件数组都视为彼此完全独立。

Well I found a fix...although it's more of a convention thing. 好吧,我找到了一个解决方法……尽管这更像是一种常规做法。 When I originally designed my code I simply used a preprocessor directive to declare my array sizes. 最初设计代码时,我只是使用预处理器指令声明数组大小。 Then I simply declared each array inside the structure. 然后我简单地声明了结构内部的每个数组。 In order to save memory I simply passed a pointer to the structures to my sub-functions. 为了节省内存,我只是将一个指向结构的指针传递给了子功能。 This meant if I was going to reference an element outside of the main() routine I used something like: 这意味着,如果要引用main()例程之外的元素,则应使用类似以下内容的内容:

grid->x;

Now and I references each element of x like 现在,我像这样引用x的每个元素

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

Of course, when a netCDF function needed a pointer to the variable it was going to store, I just passed it 当然,当netCDF函数需要指向要存储的变量的指针时,我只是将其传递了

grid->x

However, using this new memory allocation function, when I pass this to a function I'm actually passing the first address of the memory space set aside for the various pointers. 但是,使用这个新的内存分配函数时,当我将其传递给函数时,实际上是传递给各种指针预留的存储空间的第一个地址。 In essence I was passing a pointer to the wrong address in memory. 实质上,我是在传递指向内存中错误地址的指针。 All I had to do is change the passed argument to: 我要做的就是将传递的参数更改为:

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

and I get the proper array output. 然后我得到正确的数组输出。 This makes me think that when C allocates memory for an array it allocates the memory used to store the values first then it allocates the memory for the pointers which provide structure to the multidimensional array. 这让我认为,当C为数组分配内存时,它首先分配用于存储值的内存,然后为为多维数组提供结构的指针分配内存。

Maybe someone can clear this one up for me? 也许有人可以帮我解决这个问题?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM