다차원 배열의 인덱싱

Posted in SW개발 // Posted at 2023. 10. 27. 09:23
728x90
이 글은 제가 과거에 운영했던 사이트인 http://dotnet.mkexdev.net 의 글을 옮겨온 것입니다. 원본 글은 2008년 5월에 작성되었습니다.

그 전에 운영했었던 사이트(mkex.pe.kr)은 흔적도 없이 사라 졌습니다. 그속의 글들도 모두... 그래서 이 사이트도 사라지기 전에 옮기고 싶은 글을 조금씩 이 블로그로 이동시키려 합니다.
(원본글) http://dotnet.mkexdev.net/Article/Content.aspx?parentCategoryID=2&categoryID=9&ID=106

 

『 다차원 배열의 인덱싱 』

 앞서 arr[3] 과 같은 1차원 배열에서의 인덱싱 기법을 알아 보았다.

만일 arr[2][2] 와 같은 2차원 배열이라면 어떤 메커니즘으로 각 요소를 찾아 낼 수 있을 것인가?

 눈치 챘을 수도 있지만 원리는 1차원 배열과 완전 동일하다.

 1차원 배열과 마찬가지로 아래의 내용이 핵심이다.

배열은 연속된 메모리 공간에 순차적으로 저장된다

 이것은 2차원이든 3차원이든 모두 동일한 원칙이다.

 만일, arr[2][2] 라는 2차원 배열이 있다면 2 2열의 배열로써 편의상 아래와 같은 표현으로 인식했다.


그러나 실제 메모리에서는 연속된 메모리 공간에 값을 저장하게 된다. 아래 그림처럼..

, 다차원 배열 역시 연속된 공간에 순차적으로 저장되는 자료구조이기 때문에 1차원 배열과
유사한(사실은 동일한) 포인터 연산으로 각 요소에 
접근할 수 있게 되는 것이다.

그럼 샘플 하나를 보고 이해해 보자.

arr[2][2] 로 정의된 배열의 arr[1][1] 의 요소를 찾는 연산은 아래와 같다. 

a [1][1] = *( arr + ((1 * 2) * 4byte) + (1 * 4byte) ) = *(arr + 8 + 4) = *(arr + 12)  

배열의 첫 요소를 가리키는 arr 상수 포인터가 0x20을 가리키므로 arr 에서 12 byte 이동한 메모리인 0x32 를 포인팅하게 되는 것이다.

위의 식이 복잡해 보인다면 int 형 배열이기 때문에 자동으로 곱해 지는 4byte 를 생략해서 생각해 보자.

a[1][1] = *(arr + (1 * 2) + 1 ) = *(arr + 2 + 1) = *(arr + 3) 가 되어 3칸을 이동하게 되는 것이다 (int 형 메모리의 한 칸은 4byte 이므로 3칸이라 함은 12byte 이다) 

 1차원 배열과 조금 다른 점은 배열의 열 정보 즉 열 값을 곱해 주는 것이다.

Arr[2][2] 의 열 값은 2이다

메모리 구조를 보면 당연한 것이다

행과 열을 가진 배열은 순차적으로 행 단위로 저장이 되기 때문에 열의 숫자를 곱해 줘야 그만큼 메모리
이동이 가능한 것이다 ( (0,0) -> (0,1) -> (1,0) -> (1,1) ... )

아래 그림은 내부적으로 곱해 지는 4byte 를 제외한 상태에서 쌍으로 색깔로 매핑 시킨 것이다. 

참고로 다차원 배열을 포인터로 표현해 보자.

앞서 배열은 포인터이므로, 1차원 배열은 int *p = arr 이 로 표현된다고 하였다.

다차원 배열은 다음과 같이 표현되어야 배열과 포인터가 서로 같다고 할 수 있다

int (*p)[];

, int arr[2][2] 일 경우

int (*p)[2] = arr 이 성립되는 것이다

이과 같이 정의된 포인터 p  배열 포인터라 한다

주의> 배열 포인터와 포인터 배열을 혼동하지 말기 바란다.

         포인터 배열은 int *p[2] = {&a, &b} 와 같이 포인터 자체를 여러 개 가진 것을 말하는 것이다 
         (괄호의 유/무가 이런 엄청난 차이를 보이네요 ^^; )

 

이로써 다차원 배열의 인덱싱 메커니즘을 알아 보았다.

이것은 2차원뿐만 아니라 3차원 이상에서도 동일한 메커니즘이다.