배열 인덱싱의 메커니즘(arr[i] == *(arr+i))

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

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

『 배열 인덱싱의 메커니즘 』

 배열은 다수개의 요소를 가진다.
특정 요소에 접근하기 위해서는 Sequence 한 인덱싱을 사용한다.

예를 들어, int arr[] = {1,2,3} 으로 정의된 배열의 요소에 접근하기 위해서 arr[0] , arr[1], arr[2] 로 접근할 수 있다.

앞서 우리는 배열 변수는 결국 배열의 첫 번째 요소를 포인팅 하고 있는 포인터라고 배웠다.
이전 그림을 다시 보자.

이전 아티클 보기 -> 배열과 포인터의 상관관계

 그렇다면 arr[2] 와 같은 인덱싱은 어떤 처리과정을 통해 3번째 메모리 값을 가져올 수 있는 것일까?

 가장 먼저 알아야 할 중요한 내용이 있다. 

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

위의 예에서 제시된 int 형 배열 arr  0x20 번지부터 4byte 씩 증가하는 연속된 메모리 공간에 값이 저장되는
것이다

, 아래 그림과 같이 저장된다.

 

그 다음으로 알아야 할 중요한 내용이다.

배열은 포인터이다. 배열을 인덱싱은 포인터 연산으로 이루어 진다.”

일단, 배열을 알아보기 이전에 포인터 연산 중 포인터의 주소를 이동 시키는 예제를 살펴 보자.

void main(void){      
        int i = 1;
        int *p = &i;
 
        printf("%d<=포인터의주소값\n",*&p);
        p = p + 1; //포인트의주소를한칸이동한다(4byte 만큼메모리이동)      
        printf("%d<=포인트주소이동후주소값\n",*&p);
}


포인터 변수 p  1을 더한다.

이 의미는 주소 값인 p  1을 더한다는 의미로,
메모리 주소를 한 블럭 증가시키게 된다. 이때 p는 int 형이기 때문에 1 증가는 4byte 단위(블럭)의 증가를 의미한

포인터가 가지는 값은 자신이 포인팅 하고 있는 대상 메모리의 주소 값을 가지고 있다.
따라서 이 포인터의 값을 변경한다는 것은 대상 메모리 주소를 변경한다는 것과 같은 의미이다.

주의해야 할 것은 포인터 값을 증가 시킬 경우에는 포인터의 타입에 따라 자동으로 크기만큼 곱해 진다는 것
을 알아야 한다

이 경우 p  int 형 포인터이기 때문에 p + 1 = p + 1 * 4 가 된다.  내부적으로 4(byte) 가 곱해 지는 것이다.

당연하겠지만 4byte 길이 int 형 메모리 공간을 한 칸 이동 한다는 것은 4byte 만큼 이동한다는 것이기 때문이다.
(만일 자동으로 곱해지는 데이터 길이가 헷갈린다면 간편한 이해를 위해서는 그냥 메모리 한 칸 이동한다고 생각하자)

. 이제 위의 샘플을 실행한 결과를 보자.

포인터의 값이 4 만큼 증가된 것을 보여준다
결론적으로 포인터가 포인팅하는 주소 값이 변경된 것이다.

p 의 변경 전,변경 후 의 실제 포인팅 대상의 값을 보자.

포인팅 주소를 변경하기 전에는 int i =1 이었던 놈을 여전히 포인팅 하고 있고 변경 후에는 이상한 값이 나왔다.

이제 배열로 말해 보자.
다시 말하지만, 배열은 포인터 이며 위와 같은 포인터 연산으로 배열 각 요소를 인덱싱 하는 것이 가능하다

int arr[] = {1,2,3}  라고 정의된 배열이 있으며 이의 메모리 구조는 아래와 같다고 했다.

배열 변수인 arr 은 배열의 첫 번째 요소를 포인팅 하는 (상수) 포인터이다.

arr[1] 를 풀이해 보면,
arr 의 값을 1 증가시키고 그 값이 포인팅 하는 대상 메모리의 값을 가져온다.

1. arr  1 증가 (int 형 배열일 경우)

arr + 1 = arr + 1 * (4byte) 

사실 * 4byte는 생략해도 무방하다
arr 타입에 따라 메모리 블럭 증가는 해당 타입의 메모리 블럭만큼 되는 것은 당연하기 때문이다

2. arr 의 포인팅 하고 있는 대상 메모리 값 참조

*(arr + 1)

결국 arr[1] = *(arr + 1)  이다.

( *(p + 1) 의 식은 p[1] 과 동일하다)

 위의 예에서는 arr 을 한 칸 이동하면 0x24가 되고 이 메모리 주소의 값은 2가 되는 것이다.

지금까지의 내용을 그림으로 담아 보았다.

 

너무 장황하게 설명했지만, 배열의 인덱싱 메커니즘을 한마디로 한 마디로 요약하자면 다음과 같이 할 수 있겠다

연속된 메모리 공간을 포인터 연산으로 찾아가는 일련의 과정 

배열과 포인터에 관한 중요한 아래의 연산식을 기억하자
arr[i] == *(arr+i)

'SW개발' 카테고리의 다른 글

이런... 계집 녀(女)  (0) 2023.10.31
다차원 배열의 인덱싱  (0) 2023.10.27
배열과 포인터(Pointer) 의 상관관계  (0) 2023.10.27
리터럴(Literal) 상수  (0) 2023.10.27
ASCII  (0) 2023.10.27