우리가 지난 번에 배웠었던 배열과 포인터는 사실 밀접한 관계를 가지고 있습니다. 그것이 어떤 관계인지 이 포스팅을 통해서 알아보도록 하겠습니다.
배열과 포인터 표기법
포인터는 포인터가 가리키는 메모리의 시작 주소를 기준으로 삼고, 배열은 배열이 사용하는 메모리의 시작 주소를 기준으로 삼습니다. "각각의 자료형(포인터, 배열)들이 메모리의 시작 주소를 기준으로 삼는다" 이것은 배열과 포인터의 놀라운 공통점입니다. 그 말은 배열과 포인터 각각의 문법을 서로 교차해서 사용할 수 있다는 뜻이기도 합니다.
// 배열의 표기법
char data[5];
data[1] = 5;
// *(data + 1) = 5; 는 data[1] = 5와 100% 일치합니다.
*(data + 1) = 5;
// 포인터의 표기법
char data;
char *p = &data;
*p = 3;
// *p = 3; 은 p[0] = 3; 과 100% 일치합니다.
p[0] = 3;
배열의 시작 주소
우리가 배열을 사용하다 보면 궁금증이 생길 수 있습니다. 배열의 이름, 즉 "인덱스 부분을 포함하지 않은 배열은 무엇을 뜻하는 걸까?" 우리는 방금 포인터와 배열을 살펴보며 포인터와 배열은 서로 바꾸어서 표현할 수 있다는 것을 배웠습니다. 코드를 통해 이 질문의 답을 구해보고 증명해보도록 하겠습니다.
// 1. 먼저 배열을 선언해봅시다.
// (배열의 첫 번째 주소는 배열 전체의 주소와 동일합니다.)
char arr[5];
char *ptr = &arr[0];
// 2. 포인터의 덧셈과 포인터 표기를 사용해 탐구해봅시다.
char *ptr = &data[0];
char *ptr = & *(data + 0);
char *ptr = & *(data);
// 포인터 연산에서 &와 * 가 같이 있는 경우, 두 연산 모두 무효화됩니다.
char *ptr = data;
이렇게 증명함으로 "배열 변수의 이름 자체가 배열의 시작 주소이다"라는 결론을 얻을 수 있습니다.
배열은 포인터가 아니다
그렇다면 배열과 포인터는 동일한 개념이냐? 그것은 아닙니다. 배열은 배열이고, 포인터는 포인터입니다. 포인터는 "다른 변수의 주소를 저장하기 위해" 만들어진 개념이지만, 배열은 단지 "일반 변수들을 묶어놓은 것"입니다. 일반 변수들은 자신이 위치한 주소를 변경할 수 없으면, 당연히 배열 또한 자신이 위치한 주소를 바꿀 수 없습니다. 그 말은 "배열의 시작 주소 또한 변경할 수 없다는 뜻입니다." 이것이 바로 배열과 포인터의 차이점이며, 배열과 포인터가 동일한 개념이 아닌 이유입니다.