C/C++에서는 정수 포인터, 정수 상수, 상수 포인터를 조합하여 다양한 형태의 변수 선언이 가능합니다. 겉보기에는 비슷해 보이지만 각 선언이 지니는 의미는 크게 다릅니다. 이 글에서는 대표적인 세 가지 선언인 const int *, const int * const, int const *의 차이를 살펴보겠습니다.
시계 방향/나선형 규칙(Clockwise/Spiral Rule)이란?
복잡해 보이는 포인터 선언문을 해석할 때는 '시계 방향/나선형 규칙'이 매우 유용합니다. 이 규칙은 선언문의 시작점(변수 이름)에서 출발하여 시계 방향으로 돌면서 키워드를 하나씩 읽어 나가는 방식입니다. 각 선언을 하나씩 논의하며 이 규칙도 함께 익혀 보겠습니다.
1. const int *
const int *는 해당 변수가 포인터 타입이며, 상수 정수(constant int)의 주소를 저장할 수 있음을 컴파일러에 알려줍니다. 즉, 포인터가 가리키는 값은 수정할 수 없지만, 포인터 자체는 다른 주소를 가리키도록 변경될 수 있습니다. 시계 방향 규칙을 적용하면 아래 그림과 같이 해석됩니다.

2. const int * const
두 번째 선언인 const int * const는 상수 포인터 변수를 의미합니다. 이 포인터는 또 다른 상수 정수의 주소를 저장하며, 포인터가 가리키는 대상과 포인터 자체 모두 변경할 수 없습니다. 시계 방향 규칙을 적용하면 다음과 같은 문장을 얻을 수 있습니다.

3. int const *
세 번째 선언인 int const *는 변수가 포인터 타입이며 상수 정수를 가리킬 수 있음을 나타냅니다. 시계 방향 규칙을 적용하면 아래와 같이 해석됩니다.

정리
잘 살펴보면 첫 번째 선언(const int *)과 세 번째 선언(int const *)은 사실상 동일하다는 것을 알 수 있습니다. C/C++에서는 const가 타입 앞에 오든 뒤에 오든 같은 의미를 가지므로, 이 둘은 서로 바꿔 사용할 수 있습니다.
반면 두 번째 선언인 const int * const는 포인터 자체까지 상수화되므로 완전히 다른 의미를 가집니다. 요약하면 다음과 같습니다.
- const int * / int const *: 가리키는 값은 상수이지만 포인터는 변경 가능
- const int * const: 가리키는 값과 포인터 모두 상수로 변경 불가