const의 위치에 따라서 포인터가 상수인지 데이터가 상수인지 아니면 둘 다 상수인지 정해진다. 맨날 헷갈려해서 이참에 정리한다.
char greeting[] = "Hello";
// 비상수 포인터, 비상수 데이터
char *p = greeting;
// 비상수 포인터, 상수 데이터
const char *p = greeting;
// 상수 포인터, 비상수 데이터
char * const p = greeting;
// 상수 포인터, 상수 데이터
const char * const p = greeting;
C++
복사
규칙이 없어 보이지만, 자세히 보면 규칙이 있다.
바로 *을 기준으로 나눠 생각하면 된다.
const 키워드가 * 왼쪽에 있으면 포인터가 가리키는 대상(데이터)이 상수이다.
const 키워드가 * 오른쪽에 있으면 포인터 자체가 상수이란 의미다.
그리고 const가 * 양쪽에 다 있다면 포인터가 가리키는 대상 및 포인터가 다 상수라는 의미이다.
조금 더 자세히 알아보자.
규칙
const char *
#include <iostream>
using namespace std;
int main(void) {
char greeting[] = "Hello";
char world[] = "World";
const char *p = greeting;
cout << p << endl; // 혹 cpp 처음 접하는 사람은 낯선 코드가 있다고 겁먹지 말길 바란다. 그냥 출력문이다.
p = world;
cout << p << endl;
}
C++
복사
포인터가 가리키는 대상은 비상수이기 때문에, 언제든지 p가 가리키고 있는 대상을 바꿀 수 있다. 그러나 아래와 같이 동작하려고 하면 컴파일 에러가 뜰 것이다.
p[0] = 'W';
C++
복사
에러 메시지를 보면 "read-only variable is not assignable", 즉 포인터 p가 가리키고 있는 대상은 상수이기 때문에 상수의 값을 변경할 수 없는 것이다.
char * const
#include <iostream>
using namespace std;
int main(void) {
char greeting[] = "Hello";
char world[] = "world";
char * const p = greeting;
cout << p << endl;
p[0] = 'W';
cout << p << endl;
}
C++
복사
포인터가 가리키는 대상, 즉 p가 담고 있는 데이터는 비상수이기 때문에, p의 문자를 바꿀 수 있다. 그러나 포인터 자체가 상수이기 때문에 아래와 같이 사용할 수 없다.
p = world;
C++
복사
const char * const
포인터가 가리키는 대상과 데이터 모두 상수이기 때문에, 포인터가 가리키는 대상도 변경할 수 없으며, 데이터의 값도 변경할 수 없다.
Style
프로그래머마다 const를 사용하는 스타일은 조금씩 다른데, 아래와 같이 쓰는 사람들이 있다. 하지만 둘의 의미적인 차이는 전혀 없다.
// 상수 Widget 객체에 대한 포인터를 매개변수로 취함
void f1(const Widget *pw);
// 동일한 의미
void f2(Widget const *pw);
C++
복사
참고:
Meyers, S. (2005) Effective C++: 55 Specific ways to improve your programs and designs. 3rd edition. Pearson Education.