programing

말로카 3차원 배열이 C?

megabox 2023. 9. 21. 20:13
반응형

말로카 3차원 배열이 C?

일부 MATLAB 코드를 C로 변환하고 있는데 변환 중인 스크립트는 10*100*300개의 복잡한 엔트리를 가진 3D 어레이를 많이 사용합니다.배열의 크기도 센서의 입력에 따라 달라지는데, 이상적으로 배열은 동적으로 할당되어야 합니다.지금까지 두 가지 접근법을 시도했습니다. 첫 번째 접근법은 평면 1D 배열입니다.

value = array[x + (y*xSize) + (z*ySize*xSize)]

그래서 머리가 아프네요.저도 여러가지 포인터들의 배열을 시도해 봤습니다.

int main () {
  int ***array = malloc(3*sizeof(int**));
  int i, j;

  for (i = 0; i < 3; i++) {
    *array[i] = malloc(3*sizeof(int*));
    for (j = 0; j < 3; j++) {
      array[i][j] = malloc(3*sizeof(int));
    }
  }

  array[1][2][1] = 10;

  return 0;
}

데이터를 할당하려고 할 때 세그먼트 오류가 발생합니다.

완벽한 세상에서, 저는 더 깨끗하고 쉬운 프로그래밍을 위해 배열 표기법이 있는 두 번째 방법을 사용하고 싶습니다.C에서 동적으로 3차원 배열을 할당하는 더 나은 방법이 있습니까?

첫 번째 옵션(단일 1D 어레이)을 선택하면 수천 개의 조각난 메모리 블록 대신 단일 블록의 메모리를 재생할 수 있습니다.

배열의 정확한 요소에 접근하는 것이 당신의 머리에 도움이 된다면, 나는 x,y,z 위치를 오프셋으로 변환하는 유틸리티 방법을 작성할 것입니다.

int offset(int x, int y, int z) { 
    return (z * xSize * ySize) + (y * xSize) + x; 
}

다른 사람들이 말했듯이, 연속된 메모리 덩어리 하나를 할당한 후, 스스로 인덱싱을 파악하는 것이 더 나을 것입니다.당신이 원한다면 함수를 작성해도 됩니다.은 다중요에 해야 할지 것 .malloc() case,다의 가 있습니다

합니다를 합니다.free_data(), 이것은 자유롭게 해줍니다.int ***와 함께xlen그리고.ylen처음 2차원 크기로.우리는 필요 없습니다.zlen 변수와 rfree()자유롭게 하는 포인터의 길이를 사용하지 않습니다.

void free_data(int ***data, size_t xlen, size_t ylen)
{
    size_t i, j;

    for (i=0; i < xlen; ++i) {
        if (data[i] != NULL) {
            for (j=0; j < ylen; ++j)
                free(data[i][j]);
            free(data[i]);
        }
    }
    free(data);
}

합니다 에 루프를 형성합니다.data, 알아내다, 알아봅니다.iint **를 갖다 대다data[i]. 그럼, 당연한 일이지만,int **그 돌면서,jint *인에data[i][j], 자유롭게 해줄 겁니다그것은 또한 자유가 필요합니다.data[i] 것을 에.data[i][j], 그리고 마지막으로, 그것은 자유가 필요합니다.data그 자체.

이제 할당 함수입니다.오류 확인으로 기능이 조금 복잡합니다.가가 1 + xlen + xlen*ylen malloc우리는 그 어떤 전화에서도 장애를 처리할 수 있어야 하고 지금까지 할당한 모든 메모리를 해방시켜야 합니다.을 더 위해,합니다,해라는 합니다.free(NULL)합니다와 합니다.NULL오류가 발생하면 모든 포인터를 자유롭게 사용할 수 있도록 할당하기 전에.

그 외에는 기능이 충분히 간단합니다.합니다를 위한 합니다.xlen int **값에 합니다.xlen합니다, 공간을 할당합니다.ylen int *입력한 , 각에에 들.xlen*ylen합니다, 공간을 할당합니다.zlen int,합니다를 위한 하는 값들.xlen*ylen*zlen int값:

int ***alloc_data(size_t xlen, size_t ylen, size_t zlen)
{
    int ***p;
    size_t i, j;

    if ((p = malloc(xlen * sizeof *p)) == NULL) {
        perror("malloc 1");
        return NULL;
    }

    for (i=0; i < xlen; ++i)
        p[i] = NULL;

    for (i=0; i < xlen; ++i)
        if ((p[i] = malloc(ylen * sizeof *p[i])) == NULL) {
            perror("malloc 2");
            free_data(p, xlen, ylen);
            return NULL;
        }

    for (i=0; i < xlen; ++i)
        for (j=0; j < ylen; ++j)
            p[i][j] = NULL;

    for (i=0; i < xlen; ++i)
        for (j=0; j < ylen; ++j)
            if ((p[i][j] = malloc(zlen * sizeof *p[i][j])) == NULL) {
                perror("malloc 3");
                free_data(p, xlen, ylen);
                return NULL;
            }

    return p;
}

가 했습니다를 에 주목하세요.malloc다:다의 안 .malloc합니다.sizeof유형 대신 연산자입니다.서를 .malloc쓰기가 더 간단하고 오류가 덜 발생합니다.다를 .stdlib.h위해서malloc.

다음은 위의 두 가지 기능을 사용한 테스트 프로그램입니다.

#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <time.h>

int main(void)
{
    int ***data;
    size_t xlen = 10;
    size_t ylen = 100;
    size_t zlen = 300;
    size_t i, j, k;

    srand((unsigned int)time(NULL));
    if ((data = alloc_data(xlen, ylen, zlen)) == NULL)
        return EXIT_FAILURE;

    for (i=0; i < xlen; ++i)
        for (j=0; j < ylen; ++j)
            for (k=0; k < zlen; ++k)
                data[i][j][k] = rand();

    printf("%d\n", data[1][2][1]);
    free_data(data, xlen, ylen);
    return EXIT_SUCCESS;
}

이 방법을 사용하는 것이 더 쉽다면 반드시 이 방법을 사용합니다.일반적으로, 이것은 연속된 메모리 청크를 사용하는 것보다 느리겠지만, 위의 방식으로 속도가 괜찮다는 것을 발견하고, 생활을 편리하게 한다면 계속 사용할 수 있습니다.사용하지 않더라도 그런 계획을 어떻게 하면 효과를 낼 수 있는지 아는 것이 좋습니다.

를 ?malloc 배열을 만들 수 있습니다 C를 사용하면 기본적으로 다차원 배열을 생성할 수 있습니다.

int a2[57][13][7];

아니면 사용해도 좋습니다.malloc다음과 같은 방법으로

int (*a)[13][7]; // imitates 3d array with unset 3rd dimension
                 // actually it is a pointer to 2d arrays

a = malloc(57 * sizeof *a);    // allocates 57 rows

a[35][7][3] = 12; // accessing element is conventional

free(a); // freeing memory

C의 배열 유형은 컴파일 시간이 알려진 값으로만 지정할 수 있기 때문에 C89에서는 원하는 작업을 수행할 방법이 없습니다.따라서 미친 동적 할당을 피하기 위해서는 일차원적인 방법을 고수해야 할 것입니다.이 과정을 쉽게 하기 위해 함수를 사용할 수 있습니다.

int index(int x, int y, int z) {
  return x + (y*xSize) + (z*ySize*xSize);
}

int value = array[index(a, b, c)];

C99에서는 차원이 런타임 값인 경우에도 일반 배열 구문을 사용할 수 있습니다.

int (*array)[X][Y][Z] = (int(*)[X][Y][Z])malloc(sizeof *p); 
// fill...
int value = (*array)[a][b][c];

그러나 로컬 비정전 어레이에서만 작동합니다.

아 malloc 배열 할당이 싫은가요 ^^

여기 정확한 버전이 있습니다. 기본적으로 틀린 한 줄뿐입니다.

int main () {
  int ***array = (int***)malloc(3*sizeof(int**));
  int i, j;

  for (i = 0; i < 3; i++) {
    // Assign to array[i], not *array[i] (that would dereference an uninitialized pointer)
    array[i] = (int**)malloc(3*sizeof(int*));
    for (j = 0; j < 3; j++) {
      array[i][j] = (int*)malloc(3*sizeof(int));
    }
  }

  array[1][2][1] = 10;

  return 0;
}

여러분은 이것을 3D 배열을 할당하는 두 가지 근본적으로 다른 방법으로 인식하도록 강요하고 있습니다.이러한 인식은 두 가지 확실한 차별화 세부 사항에 의해 강화됩니다. 1) 두 번째 방법은 실제 요소에 액세스하기 위해 여러 수준의 간접을 사용하고, 2) 두 번째 방법은 하위 수준의 1D 배열을 독립적으로 할당합니다.

그런데 왜 하위 레벨의 1D 어레이를 독립적으로 할당해야 한다고 주장하십니까?당신은 그럴 필요가 없어.그리고 이를 고려해 보면 3D 어레이를 구축하는 세 번째 방법이 있다는 것을 깨달아야 합니다.

int ***array3d = malloc(3 * sizeof(int **));
int **array2d = malloc(3 * 3 * sizeof(int *));
int *array1d = malloc(3 * 3 * 3 * sizeof(int));

for (size_t i = 0; i < 3; i++) 
{
  array3d[i] = array2d + i * 3;
  for (size_t j = 0; j < 3; j++)
    array3d[i][j] = array1d + i * 3 * 3 + j * 3;
}

array[1][2][1] = 10;

이 할당 방법을 자세히 살펴보면, 결국 이 방법이 두 번째 방법과 거의 동일하다는 것을 알 수 있습니다. 즉, 각 방향 지시 수준에서 중간 포인터를 사용하여 3단계 배열 구조를 구축하는 것입니다. 점은 여러 신,으로,에, 입니다"면 "한 각 에 할당한다는 입니다.malloc은 그 calls 다음 사이클은 단순히 그 미리 할당된 메모리를 서브 어레이들 사이에 분배합니다(즉, 단순히 포인터들을 초기화합니다).

좀 더 메모리( )도 눈에.int는 첫됩니다. 하는s) 는됩니다.malloc(3 * 3 * 3 * sizeof(int));로. -로.

이 세 방법이 첫 방법인 , 와 크게 합니다그들은 둘 다 평평한 크기의 배열을 사용합니다.xSize * ySize * zSize데이터를 저장합니다.여기서 유일한 실질적인 차이는 해당 플랫 데이터에 액세스하기 위해 인덱스를 계산하는 방법입니다. 번째 입니다로

array1d[z * ySize * xSize + y * xSize + x]

세 번째 방법에서 우리는 배열 요소에 대한 포인터를 미리 calculate합니다. 본질적으로 동일한 공식을 사용하고, 미리 calcul된 결과를 추가 배열에 저장하고 나중에 "자연" 배열 액세스 구문을 사용하여 검색합니다.

array3d[x][y][x]

여기서 문제는 이 사전 계산이 추가적인 노력과 추가적인 기억의 가치가 있는가 하는 것입니다.답은: 일반적으로 아니오, 그렇지 않습니다.이 여분의 메모리를 사용하면 상당한 성능상의 이점을 얻을 수 없습니다(코드 속도가 느려질 가능성이 있음).

두 번째 방법을 고려할 가치가 있는 유일한 상황은 일부 하위 배열 부분이 없거나 사용되지 않거나 크기가 줄어든 희소 다차원 배열입니다.예를 들어 3D 배열의 일부 1D 또는 2D 하위 배열에 0만 포함된 것으로 알려진 경우 메모리에 저장하지 않기로 결정하고 해당 포인터를 null로 설정할 수 있습니다.이는 하위 배열이 독립적으로 할당(또는 할당되지 않음)되는 두 번째 방법을 사용함을 의미합니다.데이터가 큰 경우 결과적으로 메모리를 절약할 가치가 있습니다.

또한 3차원 이상의 어레이에 대해 이야기할 때는 여러 수준의 인다이렉션에 대해 첫 번째/두 번째/세 번째 할당 방법을 동시에 사용할 수 있습니다.첫 번째 방법을 사용하여 2D 배열을 구현한 다음 두 번째 방법을 사용하여 3D 배열로 결합할 수 있습니다.

이러한 방식으로 메모리 블록을 1개만 할당할 수 있으며 동적 배열은 정적 배열과 같이 동작합니다(즉, 동일한 메모리 연속성).일반적인 1-D 어레이와 같이 하나의 자유(배열)로 메모리를 확보할 수도 있습니다.

double*** arr3dAlloc(const int ind1, const int ind2, const int ind3)
{
  int i;
  int j;
  double*** array = (double***) malloc( (ind1 * sizeof(double*)) + (ind1*ind2 * sizeof(double**)) + (ind1*ind2*ind3 * sizeof(double)) );
  for(i = 0; i < ind1; ++i) {
    array[i] = (double**)(array + ind1) + i * ind2;
    for(j = 0; j < ind2; ++j) {
      array[i][j] = (double*)(array + ind1 + ind1*ind2) + i*ind2*ind3 + j*ind3;
    }
  }
  return array;
}

segfault 관련하여 다른 분이 지적하신 것은 확실하지만 혹시 모르니 첫번째 루프의 첫번째 줄에 '*'가 추가로 있습니다.

for (i = 0; i < 3; i++) {
    *array[i] = malloc(3*sizeof(int*));
//  ^ we dont want to deference array twice
    for (j = 0; j < 3; j++) {
        array[i][j] = malloc(3*sizeof(int));
    }
}

다음을 시도해 봅니다.

    for (i = 0; i < 3; i++) {
        array[i] = malloc(3*sizeof(int*));
        for (j = 0; j < 3; j++) {
            array[i][j] = malloc(3*sizeof(int));
        }
    }

이것이 당신에게 도움이 되기를 바랍니다!!!!

3D 어레이 내부의 2D 어레이에 메모리를 할당하는 동안 할당된 메모리를 *array[i]가 아닌 array[i]에 할당하면 세그먼트 오류 없이 작동합니다.

여기 당신의 프로그램이 있습니다.

int main () 
{
    int ***array = malloc(3*sizeof(int**));
    int i, j;

    for (i = 0; i < 3; i++) {
       array[i] = malloc(3*sizeof(int*));
       for (j = 0; j < 3; j++) {
          array[i][j] = malloc(3*sizeof(int));
       }
    }

    array[1][2][1] = 10;

    return 0;
}

여기 같은 것이 있습니다만, 전화 만 걸려오면 됩니다.

void* allocate_3d_matrix(size_t size, size_t r1, size_t r2, size_t r3) {
    size_t malloc_size = r1 * sizeof(char**) + r1 * r2 * sizeof(char*) + r1 * r2 * r3 * size;
    char*** p = malloc(malloc_size);

    char** r2_start = (char**) p + r1;  

    for (int i = 0; i < r1; i++) {
        p[i] = r2_start + i * r2;
    }

    char* r3_start = (char*) r2_start + (r1 * r2 * sizeof(char*));

    for (int i = 0; i < r1; i++) {
        for (int j = 0; j < r2; j++) {
            p[i][j] = r3_start + size * (j + i * r2) * r3;
        }
    }

    return p;
}

free(p) 것이 되어 있기 입니다.에서는 가장 하는데,다때로 한 합니다.malloc(메모리 조각화 감소).

3D 메모리 할당 코드 아래:

int row3d = 4;
int column3d = 4;
int height3d =4;
int val3d =10;

int ***arr3d = (int***)malloc (row3d*sizeof(int**));
for (int i =0 ; i<column3d;i++)
{
    arr3d[i] = (int**)malloc (column3d*sizeof(int*));
    for (int j = 0;j<height3d;j++)
    {
        arr3d[i][j] = (int*)malloc (height3d*sizeof(int));

        for (int z =0;z<height3d;z++,val3d++)
        {
            arr3d[i][j][z]   = val3d;
        }
    }

}
// De allocation.
for (int i=0;i<row3d;i++)
{
    for(int j=0;j<column3d;j++)
    {
        free(arr3d[i][j]);
    }
}
free(arr3d);
arr3d = 0;
#include<stdio.h>
#include<stdlib.h>

#define MAXX 3
#define MAXY 4
#define MAXZ 5

main()
{
    int ***p,i,j;
    p=(int ***) malloc(MAXX * sizeof(int **));

    for(i=0;i < MAXX;i++)
    {
        p[i]=(int **)malloc(MAXY * sizeof(int *));
        for(j=0;j < MAXY;j++)
            p[i][j]=(int *)malloc(MAXZ * sizeof(int));
    }

    for(k=0;k < MAXZ;k++)
        for(i=0;i < MAXX;i++)
            for(j=0;j < MAXY;j++)
                p[i][j][k]= < something >;

}

#include "stdlib"을 추가합니다.h" 및 *array[i]에서 *를 제거하면 Ubuntu에서 gcc 4.4.1로 컴파일될 때 실행됩니다.

또한 인쇄문을 추가하면 버그를 더 빨리 찾을 수 있습니다.

#include <stdio.h>
#include <stdlib.h>

int main () {
  int ***array = malloc(3*sizeof(int**));
  int i, j;

  printf("%s\n","OK");

  for (i = 0; i < 3; i++) {
    printf("i = %i \n",i);
    array[i] = malloc(3*sizeof(int*));
    for (j = 0; j < 3; j++) {
      printf("i,j = %i,%i \n",i,j);
      array[i][j] = malloc(3*sizeof(int));
    }
  }

  array[1][2][1] = 10;

  return 0;
}

p와 p[0], 그리고 p[0][0]에 대해 메모리를 할당할 것을 제안하는 프로세스를 이해하기 위해 다음은 간단한 예입니다.

   int ***a;
     a  = (int***)malloc(sizeof(int**));
    *a  = (int**)malloc(sizeof(int*));
   **a  = (int*)malloc(sizeof(int));
#include <stdio.h>
#include <stdlib.h>

int*** allocate_memory(int rows, int columns, int heigth) {
    int ***array = (int***) malloc(rows * sizeof(int**));

    for (int i = 0; i < rows; i++) {
        array[i] = (int**) malloc(columns * sizeof(int*));
        for (int j = 0; j < columns; j++) {
            array[i][j] = (int*) malloc(heigth * sizeof(int));
        }
    }

    array[1][2][1] = 10;
    return array;
}

int main() {
    int ***cube = allocate_memory(3, 3, 3);
    printf("%d\n", cube[1][2][1]);
    return 0;
}

이 방법이 작동해야 합니다. malloc의 반환 값을 입력하지 않았습니다.

#include <stdio.h>

int main () {
  int ***array = (int ***) malloc(3*sizeof(int**));
  int i, j;

  for (i = 0; i < 3; i++) {
    array[i] = (int **)malloc(3*sizeof(int*));
    for (j = 0; j < 3; j++) {
      array[i][j] = (int *)malloc(3*sizeof(int));
    }
  }

  array[1][2][1] = 10;
  printf("%d\n", array[1][2][1]);
  return 0;
}

작업 링크: http://ideone.com/X2mcb8

언급URL : https://stackoverflow.com/questions/2306172/malloc-a-3-dimensional-array-in-c

반응형