programing tip

다차원 배열은 메모리에서 어떻게 포맷됩니까?

itbloger 2020. 6. 1. 19:06
반응형

다차원 배열은 메모리에서 어떻게 포맷됩니까?


C에서는 다음 코드를 사용하여 힙에 2 차원 배열을 동적으로 할당 할 수 있다는 것을 알고 있습니다.

int** someNumbers = malloc(arrayRows*sizeof(int*));

for (i = 0; i < arrayRows; i++) {
    someNumbers[i] = malloc(arrayColumns*sizeof(int));
}

분명히 이것은 실제로 정수로 구성된 여러 개의 1 차원 배열에 대한 포인터의 1 차원 배열을 만들고 "시스템"은 내가 요청할 때 의미하는 바를 알아낼 수 있습니다.

someNumbers[4][2];

그러나 다음 줄과 같이 2D 배열을 정적으로 선언하면 ... :

int someNumbers[ARRAY_ROWS][ARRAY_COLUMNS];

... 스택에서 유사한 구조가 생성됩니까? 아니면 완전히 다른 형태입니까? (즉, 포인터의 1D 배열입니까? 그렇지 않은 경우, 무엇이며, 이에 대한 참조는 어떻게 파악됩니까?)

또한 "시스템"이라고 말했을 때 실제로 그것을 알아내는 데 책임이있는 것은 무엇입니까? 커널? 아니면 C 컴파일러가 컴파일하는 동안 정렬합니까?


정적 2 차원 배열은 배열 배열처럼 보입니다. 메모리에 연속적으로 배치되어 있습니다. 배열은 포인터와 같지 않지만, 종종 그것들을 거의 상호 교환 적으로 사용할 수 있기 때문에 때때로 혼란 스러울 수 있습니다. 그러나 컴파일러는 올바르게 추적하므로 모든 것이 잘 정렬됩니다. 언급 한 것처럼 정적 2D 배열에주의해야합니다. int **매개 변수 를받는 함수에 1을 전달하려고하면 나쁜 일이 발생할 수 있기 때문입니다. 다음은 간단한 예입니다.

int array1[3][2] = {{0, 1}, {2, 3}, {4, 5}};

메모리에서 다음과 같습니다.

0 1 2 3 4 5

정확히 다음과 같습니다.

int array2[6] = { 0, 1, 2, 3, 4, 5 };

그러나이 array1기능 에 전달하려고하면 :

void function1(int **a);

경고 메시지가 표시되고 앱이 배열에 올바르게 액세스하지 못합니다.

warning: passing argument 1 of ‘function1’ from incompatible pointer type

2D 배열이와 같지 않기 때문 int **입니다. 배열에서 포인터로의 자동 소멸은 말하기를 "한 수준 깊이"만 진행합니다. 함수를 다음과 같이 선언해야합니다.

void function2(int a[][2]);

또는

void function2(int a[3][2]);

모든 것을 행복하게 만듭니다.

이 같은 개념은 n 차원 배열로 확장됩니다 . 응용 프로그램에서 이러한 종류의 재미있는 비즈니스를 활용하면 일반적으로 이해하기가 더 어려워집니다. 그러니 조심하세요


답은 C가 정말하지 않는 생각을 기반으로 2 차원 배열을 - 그것은 배열 - 중 - 배열을 가지고있다. 이것을 선언하면 :

int someNumbers[4][2];

someNumbers4 개의 요소로 구성된 배열을 요구합니다 . 여기서 해당 배열의 각 요소는 유형입니다 int [2](자체 배열은 2 int초).

퍼즐의 다른 부분은 배열이 항상 메모리에 연속적으로 배치된다는 것입니다. 요청하는 경우 :

sometype_t array[4];

그러면 항상 다음과 같이 보일 것입니다.

| sometype_t | sometype_t | sometype_t | sometype_t |

(4 개의 sometype_t물체가 서로 간격을두고 배치되지 않음). 따라서 someNumbers배열 배열에서 다음과 같이 나타납니다.

| int [2]    | int [2]    | int [2]    | int [2]    |

그리고 각 int [2]요소 자체는 다음과 같은 배열입니다.

| int        | int        |

전체적으로 다음과 같은 결과를 얻습니다.

| int | int  | int | int  | int | int  | int | int  |

unsigned char MultiArray[5][2]={{0,1},{2,3},{4,5},{6,7},{8,9}};

메모리에서 다음과 같습니다.

unsigned char SingleArray[10]={0,1,2,3,4,5,6,7,8,9};

컴파일러도 많은 노력을 기울이고 있지만 둘 다 대답합니다.

정적으로 할당 된 배열의 경우 "시스템"이 컴파일러가됩니다. 스택 변수처럼 메모리를 예약합니다.

malloc의 배열의 경우, "시스템"은 malloc (일반적으로 커널)의 구현자가됩니다. 컴파일러가 할당 할 모든 것은 기본 포인터입니다.

컴파일러는 Carl이 상호 교환 가능한 사용법을 파악할 수있는 위치에서 제공 한 예를 제외하고는 선언 된대로 항상 형식을 처리합니다. 따라서 [] []를 함수에 전달하면 정적으로 할당 된 플랫이라고 가정해야합니다. 여기서 **는 포인터를 가리키는 포인터입니다.


특정 2D 배열에 액세스하려면 아래 코드와 같이 배열 선언에 대한 메모리 맵을 고려하십시오.

    0  1
a[0]0  1
a[1]2  3

각 요소에 액세스하려면 매개 변수로 관심있는 배열을 함수에 전달하기에 충분합니다. 그런 다음 열에 오프셋을 사용하여 각 요소에 개별적으로 액세스하십시오.

int a[2][2] ={{0,1},{2,3}};

void f1(int *ptr);

void f1(int *ptr)
{
    int a=0;
    int b=0;
    a=ptr[0];
    b=ptr[1];
    printf("%d\n",a);
    printf("%d\n",b);
}

int main()
{
   f1(a[0]);
   f1(a[1]);
    return 0;
}

참고 URL : https://stackoverflow.com/questions/2565039/how-are-multi-dimensional-arrays-formatted-in-memory

반응형