programing

One malloc 문을 사용하여 2-D 배열을 할당하는 방법

codeshow 2023. 9. 19. 21:31
반응형

One malloc 문을 사용하여 2-D 배열을 할당하는 방법

저는 인터뷰에서 2-D 배열을 어떻게 할당하는지 질문을 받았고, 아래가 제 해결책이었습니다.

#include <stdlib.h>

int **array;
array = malloc(nrows * sizeof(int *));

for(i = 0; i < nrows; i++)
{
    array[i] = malloc(ncolumns * sizeof(int));
    if(array[i] == NULL)
    {
        fprintf(stderr, "out of memory\n");
        exit or return
    }
}

나는 내가 잘했다고 생각했는데 그는 나에게 그것을 사용해서 하라고 했습니다.malloc()두개가 아닌 진술.저는 그것을 어떻게 달성해야 할지 전혀 모르겠습니다.

혼자 할 수 있는 방법을 제안해 줄 수 있는 사람?malloc()?

두 가지 모두에 필요한 총 메모리 양을 계산하기만 하면 됩니다.nrows행 pointers와 실제 데이터를 모두 합산한 후 한 번의 통화를 수행합니다.

int **array = malloc(nrows * sizeof *array + (nrows * (ncolumns * sizeof **array));

너무 복잡해 보이는 경우에는 크기 표현식의 다른 용어를 지정하여 이를 분할하여 약간의 자체 문서화할 수 있습니다.

int **array; /* Declare this first so we can use it with sizeof. */
const size_t row_pointers_bytes = nrows * sizeof *array;
const size_t row_elements_bytes = ncolumns * sizeof **array;
array = malloc(row_pointers_bytes + nrows * row_elements_bytes);

그런 다음 각 행의 포인터가 해당 행의 첫 번째 요소를 가리킬 수 있도록 행 포인터를 검토하고 초기화해야 합니다.

size_t i;
int * const data = array + nrows;
for(i = 0; i < nrows; i++)
  array[i] = data + i * ncolumns;

결과적인 구조는 예를 들어 당신이 얻는 것과 미묘하게 다르다는 것에 유의하십시오.int array[nrows][ncolumns], 명시적인 행 포인터가 있기 때문에 이렇게 할당된 배열의 경우 모든 행에 동일한 수의 열이 있어야 한다는 실질적인 요구 사항은 없습니다.

그것은 또한 다음과 같은 접근을 의미합니다.array[2][3]실제 2D 배열로 유사한 모양의 액세스와 구별되는 작업을 수행합니다.이 경우 가장 안쪽에 있는 접근이 먼저 일어나고,array[2]세번째 요소에서 포인터를 읽어냅니다.array. 그런 다음 포인터를 (열) 배열의 기본으로 취급하고, 이 배열 안으로 색인을 붙여 네 번째 요소를 가져옵니다.

그에 비해, 어떤 것에 대해서는

int array2[4][3];

12개의 정수의 공간을 차지하는 "포장된" 적절한 2D 배열입니다. 접근은 다음과 같습니다.array[3][2]는 단순히 요소를 얻기 위해 기본 주소에 오프셋을 추가하는 것으로 분류됩니다.

int **array = malloc (nrows * sizeof(int *) + (nrows * (ncolumns * sizeof(int)));

이것은 C에서 배열들이 바이트들의 묶음으로서 차례로 모든 요소들이기 때문에 작동합니다.메타데이터 같은 것이 없습니다. malloc()는 배열에서 문자, int 또는 줄로 사용하기 위해 할당하는 것인지 알 수 없습니다.

그런 다음 초기화해야 합니다.

int *offs = &array[nrows]; /*  same as int *offs = array + nrows; */
for (i = 0; i < nrows; i++, offs += ncolumns) {
    array[i] = offs;
}

다른 방법이 있습니다.

컴파일 시 열 수를 알고 있다면 다음과 같은 작업을 수행할 수 있습니다.

#define COLS ... // integer value > 0
...
size_t rows;
int (*arr)[COLS];
...              // get number of rows
arr = malloc(sizeof *arr * rows);
if (arr)
{
  size_t i, j;
  for (i = 0; i < rows; i++)
    for (j = 0; j < COLS; j++)
      arr[i][j] = ...;
}

C99에서 작업하는 경우 VLA의 포인터를 사용할 수 있습니다.

size_t rows, cols;
...               // get rows and cols
int (*arr)[cols] = malloc(sizeof *arr * rows);
if (arr)
{
  size_t i, j;
  for (i = 0; i < rows; i++)
    for (j = 0; j < cols; j++)
      arr[i][j] = ...;
}

One malloc 문(?)을 사용하여 2-D 배열을 할당하는 방법

아직까지 진정한 2D 배열을 위해 메모리를 할당하는 답변은 없습니다.

int **arrayint에 대한 포인터입니다.array는 2D 배열의 포인터가 아닙니다.

int a[2][3]int의 배열 3의 실제 2D 배열 또는 배열 2의 예입니다.


C99를 사용하여 실제 2D 배열을 위한 메모리를 할당하려면 다음을 사용합니다.malloc()VLA(Variable-Length Array)의 포인터에 저장합니다.

// Simply allocate and initialize in one line of code
int (*c)[nrows][ncolumns] = malloc(sizeof *c);

if (c == NULL) {
  fprintf(stderr, "out of memory\n");
  return;
} 
// Use c
(*c)[1][2] = rand();
...
free(c);

VLA 지원 없이 치수가 상수인 경우 코드가

#define NROW 4
#define NCOL 5
int (*d)[NROW][NCOL] = malloc(sizeof *d);

이 작업을 수행할 수 있어야 합니다. (모든 캐스팅에서 약간 추합니다.)

int** array;
size_t pitch, ptrs, i;   
char* base; 
pitch = rows * sizeof(int);
ptrs = sizeof(int*) * rows;
array = (int**)malloc((columns * pitch) + ptrs);
base = (char*)array + ptrs;
for(i = 0; i < rows; i++)
{
    array[i] = (int*)(base + (pitch * i));
}

저는 다차원 배열 패러다임을 해결하기 위한 이러한 "배열 포인터 배열"의 팬이 아닙니다.배열[행 * cols + col]로 요소에 액세스할 때 항상 단일 차원 배열을 선호합니까?클래스의 모든 것을 캡슐화하고 'at' 메서드를 구현하는 데 문제가 없습니다.

Matrix[i][j]라는 표기를 사용하여 배열의 멤버에 액세스하려면 약간의 C++ 마법을 수행할 수 있습니다.@John 솔루션은 이러한 방식으로 수행하려고 하지만 컴파일 시간에 열의 수를 알아야 합니다.일부 C++와 연산자[]를 재정의하면 다음을 완전히 얻을 수 있습니다.

class Row
{
private:
    int* _p;

public:
    Row( int* p )                   { _p = p; }
    int& operator[](int col)        { return _p[col]; }
};


class Matrix
{
private:
    int* _p;
    int _cols;

public:
    Matrix( int rows, int cols )  { _cols=cols; _p = (int*)malloc(rows*cols ); }
    Row operator[](int row)       { return _p + row*_cols; }
};

이제 행렬 개체를 사용하여 곱셈 테이블을 만들 수 있습니다.

Matrix mtrx(rows, cols);
for( i=0; i<rows; ++i ) {
    for( j=0; j<rows; ++j ) {
        mtrx[i][j] = i*j;
    }
}

이제 옵티마이저가 옳은 일을 하고 있고 통화 기능이나 다른 종류의 오버헤드가 없기 때문입니다.생성자를 호출하지 않습니다.함수 간에 행렬을 이동하지 않는 한 _cols 변수도 생성되지 않습니다.mtrx[i][j]는 기본적으로 mtrx[i*cols+j]를 수행합니다.

다음과 같이 수행할 수 있습니다.

#define NUM_ROWS 10
#define NUM_COLS 10

int main(int argc, char **argv)
{
    char (*p)[NUM_COLS] = NULL;
    p = malloc(NUM_ROWS * NUM_COLS);
    memset(p, 81, NUM_ROWS * NUM_COLS);
    p[2][3] = 'a';
    for (int i = 0; i < NUM_ROWS; i++) {
        for (int j = 0; j < NUM_COLS; j++) {
            printf("%c\t", p[i][j]);
        }
        printf("\n");
    }
} // end of main

합니다.(row*column) * sizeof(int)malloc리를 .여기 시연할 코드 조각이 있습니다.

int row = 3, col = 4;
int *arr = (int *)malloc(row * col * sizeof(int));

int i, j, count = 0;
for (i = 0; i <  r; i++)
  for (j = 0; j < c; j++)
     *(arr + i*col + j) = ++count; //row major memory layout

for (i = 0; i <  r; i++)
  for (j = 0; j < c; j++)
     printf("%d ", *(arr + i*col + j));

언급URL : https://stackoverflow.com/questions/8740195/how-do-we-allocate-a-2-d-array-using-one-malloc-statement

반응형