작은숲:위키노트/초보자를 위한 C 언어 강의/배열과 포인터
배열(Array)은 특별한 포인터(Pointer)라고 생각할 수 있다. 실제로 배열을 선언하게 되면, 이 배열을 위해 일정 크기, 즉 배열의 크기만큼 연속된 공간에 메모리를 할당한다. 이렇게 할당된 메모리를 우리는 배열의 이름과 인덱스를 이용해서 접근할 수 있다. 즉, 아래와 같이 사용할 수 있다.
int array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
array[3] = array[1] + array[2];위에서 배열은 특별한 형태의 포인터라고 말했는데 배열의 어느 부분이 포인터일까? 그것은 배열의 이름 자체가 포인터이다. 이 배열의 이름은 배열의 시작 주소를 가리키고 있는 포인터가 된다. 하지만 일반 포인터와는 다르게 이 배열의 이름은 값을 변경할 수 없는 포인터가 된다. 왜 그럴까? 이유는 간단하다. 이 배열을 위해 일정 공간의 메모리가 할당되었다. 이 할당된 메모리의 시작 주소가 배열의 이름에 포인터로 저장된다. 그런데 이 주소를 바꿔버린다면, 배열의 시작 주소가 바뀌게 되는 것이다. 배열의 시작 주소가 바뀌면 이 배열은 그곳을 시작 주소로 해서 배열의 크기만큼 사용할려고 할 것이다. 하지만 그 공간은 배열에게 할당된 공간이 아니다. 즉 남의 영역이라는 말이다. 남의 영역을 함부러 사용하려고 했다가는 큰일 난다. 메모리상에서도 마찬가지이다. 자신에게 할당된 공간이 아닌 다른 곳을 사용하다가는 어떤 일이 일어날 지 아무도 장담할 수 없다. 심한 경우 시스템 에러가 발생하게 된다. 이제 배열의 이름이 배열의 시작 주소를 가리키는 포인터라는 것을 알게 되었다. 그럼 아래의 예를 보고 생각해보자.
int array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
*(array + 3) = array[1] + *(array + 2);참조 연산자(*)는 포인터 공부할 때 봤을 것이다. 이 참조 연산자를 이용하면 포인터를 이용해서 배열의 내용을 참조할 수 있다. 실제로 array[1]은 *(array + 1)과 같다. 사람이 보기에는 array[1]이 훨씬 보기 편하지만, 컴퓨터의 입장에서는 *(array + 1)이 훨씬 편하다. 그래서 컴파일할 때 컴퓨터의 입장에서 보기 편하게 변환된다. 따라서 *(array + 1)이라고 써도 array[1]과 다를 바가 없다.
그리고 다음 예를 보자.
int array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
*(++array) = array[0];위에서 *(++array) 연산이 의미하는 바가 무엇일까? 이 연산의 의미는 먼저 array가 가리키는 주소를 한 칸 이동시킨 다음에 그곳의 값을 취한다는 말이다. 하지만, 이 연산이 가능할까? 그렇다. 불가능하다. 왜 그럴까? 위에서 말했지만 배열의 이름이 포인터이기는 하지만 그 값을 변경할 수 없다고 했다. 변경하게 된다면 큰일 난다. 따라서 이런 연산은 불가능하다.
이런 식의 연산을 하고 싶다면 아래와 같이 하면 된다.
int array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *ptr;
ptr = array;
*(++ptr) = array[0];이런 식으로 포인터 변수를 선언하고 이 포인터에 배열의 시작 주소를 대입시킨다. 그럼 이 포인터는 배열 array와 같다. 배열의 시작 주소를 가지고 있기 때문이다. 포인터 변수의 경우 증가 연산이 가능하기 때문에 *(++ptr)의 의미는 결국 array[1]과 똑같다. 그리고 아래와 같이 사용할 수도 있다.
int array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *ptr;
ptr = array;
ptr[1] = array[0];ptr과 array가 가리키는 주소가 같기 때문에 ptr[1]은 결국 array[1]과 같다.
바로 이것이 배열과 포인터의 관계이다. 결국 배열은 포인터이다. 단, 그 시작 주소를 바꿀 수 없는 포인터가 되는 것이다. 그러니까 배열을 포인터처럼, 포인터를 배열처럼 사용하는 게 가능하다. 단, 배열의 이름이 가리키는 주소만 바꾸지 않는다면 말이다.