簡體   English   中英

多維數組的連續內存

[英]Contiguous memory for multidimensional array

我相信這段代碼會強制3D數組的內存分配是連續的。

void ***calloc_3d_array(size_t n3, size_t n2, size_t n1, size_t size){
  void ***array;
  size_t i, j;

  if ((array = (void***)calloc(n3, sizeof(void**))) == NULL) {
    printf("[calloc_3d] failed to allocate memory for %d 1st-pointers\n",
              (int)n3);
    return NULL;
  }

  if ((array[0] = (void**)calloc(n3*n2, sizeof(void*))) == NULL) {
    printf("[calloc_3d] failed to allocate memory for %d 2nd-pointers\n",
              (int)(n3*n2));
    free((void*)array);
    return NULL;
  }

  for (i=1; i<n3; i++) {
    array[i] = (void**)((unsigned char*)array[0]+i*n2*sizeof(void*));
  }

  if ((array[0][0] = (void*)calloc(n3*n2*n1, size)) == NULL) {
    printf("[calloc_3d] failed to alloc. memory (%d X %d X %d of size %d)\n",
              (int)n3, (int)n2, (int)n1, (int)size);
    free((void*)array[0]);
    free((void*)array);
    return NULL;
  }

  for (j=1; j<n2; j++) {
    array[0][j] = (void**)((unsigned char*)array[0][j-1]+n1*size);
  }

  for (i = 1; i < n3; i++) {
    array[i][0] = (void**)((unsigned char*)array[i-1][0]+n2*n1*size);
    for (j = 1; j < n2; j++) {
      array[i][j] = (void**)((unsigned char*)array[i][j-1]+n1*size);
    }
  }

  return array;
}

我試圖將其更改為一個連續分配4維數組的函數。 我不完全理解3D情況是否完美無缺,因此抽象到第4維有點不穩定。 我幾乎不確定到底為什么在任何循環中3d代碼中都有array [i] =(void **)或array [i] [j] =(void **),所以在4d代碼中我擁有所有數組[i] [j] [k] =(void ***)。 這是我目前擁有的

void ****calloc_4d_array(size_t n4, size_t n3, size_t n2, size_t n1, size_t size){
  void ****array;
  size_t i, j, k;

  /* Alloc array of 3d pointers */
  if ((array = (void****)calloc(n4, sizeof(void***))) == NULL) {
    printf("[calloc_3d] failed to allocate memory for %d 1st-pointers\n",
              (int)n4);
    return NULL;
  }

  /* In first slot allocate a entire 2d pointer array */
  if ((array[0] = (void***)calloc(n4*n3, sizeof(void**))) == NULL) {
    printf("[calloc_3d] failed to allocate memory for %d 2nd-pointers\n",
              (int)(n4*n3));
    free((void*)array);
    return NULL;
  }

  /* Loop over slots and adjust address to accommodate 2d pointers */
  for (i = 1; i < n4; i++) {
    array[i] = (void***)((unsigned char*)array[0]+i*n3*sizeof(void**));
  }

  /* In the first 2d pointer, allocate the entire space for 1d pointers*/
  if ((array[0][0] = (void**)calloc(n4*n3*n2, sizeof(void*))) == NULL) {
    printf("[calloc_3d] failed to allocate memory for %d 3rd-pointers\n",
              (int)(n4*n3*n2));
    free((void*)array[0]);
    free((void*)array);
    return NULL;
  }

  /* Loop over other 2d slots and adjust address to accommodate type */
  for (j=1; j<n3; j++) {
    array[0][j] = (void**)((unsigned char*)array[0][j-1]+n2*size);
  }
  for (i=1; i<n4; i++) {
    array[i][0] = (void**)((unsigned char*)array[i-1][0]+n3*n2*size);
    for (j=1; j<n3; j++) {
      array[i][j] = (void**)((unsigned char*)array[i][j-1]+n2*size);
    }
  }

  /* Finally allocate for entire array */
  if ((array[0][0][0] = (void*)calloc(n4*n3*n2*n1, size)) == NULL) {
    printf("[calloc_3d] failed to alloc. memory (%d X %d X %d X %d of size %d)\n",
              (int)n4, (int)n3, (int)n2, (int) n1, (int)size);
    free((void*)array[0][0]);
    free((void*)array[0]);
    free((void*)array);
    return NULL;
  }


  for (k=1; k<n2; k++) {
    array[0][0][k] = (void***)((unsigned char*)array[0][0][k-1]+n1*size);
  }
  for (j=1; j<n3; j++) {
    array[0][j][0] = (void***)((unsigned char*)array[0][j-1][0]+n2*n1*size);
    for (k=1; k<n2; k++) {
      array[0][j][k] = (void***)((unsigned char*)array[0][j][k-1]+n1*size);
    }
  }
  for(i=1; i<n4; i++) {
    array[i][0][0] = (void***)((unsigned char*)array[i-1][0][0]+n3*n2*n1*size);
    for (j=1; j<n3; j++) {
      array[i][j][0] = (void***)((unsigned char*)array[i][j-1][0]+n2*n1*size);
      for (k=1; k<n2; k++) {
        array[i][j][k] = (void***)((unsigned char*)array[i][j][k-1]+n1*size);
      }
    }
  }

  return array;
}

編輯 :編譯器給了我一個有關(void ***)問題的警告,似乎array [] []是(void **)是有意義的,但我仍然不知道為什么它很高興用array [i] =(void ***)代替array [i] =(void *)。 換句話說,為什么用calloc array[0][0][0] = (void*)calloc(n4*n3*n2*n1, size) (void array[0][0][0] = (void*)calloc(n4*n3*n2*n1, size) ,但是在使用位移/設置地址(?) array[0][0][k] = (void***)((unsigned char*)array[0][0][k-1]+n1*size); 我認為無論哪種對象array [] [] []都是(void *)或(void ***)。

這應該分配2個及以上維度數組,並連續使用遞歸。 建議將FORTRAN用於此類高維計算,這不是高效的內存。 該示例似乎valgrind很干凈。

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void *alloc_nd(int *dim, int nd, size_t size)
{
    assert(nd>=2);
    void **p = malloc(sizeof(void*)*dim[0]);
    if(nd==2) {
        p[0] = malloc(size*dim[0]*dim[1]);
        for(int i=1; i<dim[0]; i++)
            p[i] = p[i-1]+size*dim[1];
    } else {
        int xd[nd-1]; 
        for(int i=1; i<nd; i++)
            xd[i-1] = dim[i];
        xd[0] *= dim[0];        //callapse the 1st two dimension
        p[0] = alloc_nd(xd, nd-1, size);
        for(int i=1; i<dim[0]; i++)
            p[i] = p[i-1]+sizeof(void*)*dim[1];
    }
    return p;
}

void free_nd(void *p, int nd)
{
    if(nd==2) {
        free(((void**)p)[0]);
        free(p);
    } else {
        free_nd(((void**)p)[0], nd-1);
        free(p);
    }
}

int main()
{
    int dim[] = {3,4,5,6};
    int ****array;
    array = (int****)alloc_nd(dim, 4, sizeof(int));
    for(int i0=0; i0<dim[0]; i0++)
        for(int i1=0; i1<dim[1]; i1++)
            for(int i2=0; i2<dim[2]; i2++)
                for(int i3=0; i3<dim[3]; i3++)
                    array[i0][i1][i2][i3] = i0+i1+i2+i3;
    int *p = &array[0][0][0][0];  //do you mean continuous in this way? 
    for(int i=0; i<dim[0]*dim[1]*dim[2]*dim[3]; i++)
        printf("p[%5d]=%d\n", i, p[i]);
    free_nd(array, 4);
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM