반응형
const 키워드
C 언어에서 const는 읽기 전용 변수로 만들어주는 예약어일 뿐
완벽한 상수 기능을 갖도록 해주지 못했다.
const int n; // 초기값 오류 없음
char str[n]; // 배열의 요소 개수로 사용불가
int* p = &n; // warning
*p = 10; // 변경 가능
하지만 C++에서는
완벽히 상수화(化) 시켜주는 예약어로 사용된다.
C++은 반드시 선언시 초기값을 선언하게 되었다.
const int n = 10; // must be initialized
char str[n]; // 배열의 요소 개수로 사용 가능
int* p = &n; // error (cannot convert from 'const int *' to 'int *’)
const int* cp = &n;
// *cp = 10; // 변경 불가
★ 포인터에 예약어 const의 적극적인 사용 권장
함수 이름에 const를 포함한 const 멤버함수는 컴파일 시간에
멤버데이터의 변경을 검사(compile-error)할 수도 있게 하지만
const 개체가 안전하게 호출할 수 있는 멤버함수임을 표시하기도 하고
코드의 가독성을 높이기 위한 적극적인 표현이기도 하다.
생성자함수, 소멸자함수, static멤버함수는 const멤버함수로 둘 수 없다.
ex) 생성자 함수에서 값을 대입(변경)할 수 있기에 생성자와 소멸자에서는 const 불가
int data = 5;
// 오직 data만 가리킬거야, 난 변하지 않아.
// 포인터 변수를 고정, 바로 초기화 해야 됨
// 가리키는 대상이 const인지 아닌지는 중요 X
// 다른 애를 가리킬 수 없음
int* const p = &data;
// 읽기만 할거야 (가리키는 대상을 바꿀 수 없음)
// 포인터 변수가 가르키는 변수가 const 여부는 중요 X
const int * onlyread;
// 오직 data만을 가리키고 그 대상을 읽기만 할거야.
const int* const p = &data;
const int cdata = 5;
// 가리키는 데이터는 const int(int const)형이야
// 읽기만 하는데 포인터 변수가 가르키는 대상이 const 변수다!
int const* icp = &cdata;
포인터 변수와 const 키워드
아래 두 구문은 차이가 존재합니다.
① const int *ptr = #
② int * const ptr = #
[첫번째]는 포인터 변수 ptr이 가리키는 변수에 저장된 값 변경을 허용하지 않는 것입니다.
하지만 변수 num 자체는 상수가 아니기 때문에 변경이 가능합니다.
즉, const 선언은 값 변경에 제한을 두지만 상수화 하는 것은 아닙니다.
int num = 20;
const int *ptr = #
*ptr = 30; // 포인터 변수를 이용한 실제 값 변경 시도시 컴파일 에러
num = 40; // num 자체가 상수는 아니기 때문에 변경 가능
[두번째] 경우는 포인터 변수를 상수화 시키는 경우로,
한번 주소 값이 저장되면 그 주소값 변경이 불가능합니다.
하지만 포인터 변수가 가리키기 시작한 변수는 변경할 수 있습니다.
int num = 20;
int* const ptr = #
int value = 30;
ptr = &value; // 컴파일 에러
*ptr = 40; // 컴파일 성공
두가지 const 형태를 동시에도 가능
const int* const ptr = &num
*ptr = 20; // 컴파일 에러
ptr = &value; // 컴파일 에러
이때는, 포인터 변수의 변경도 안되고, 가리키고 있는 변수 값의 변경도 되지 않습니다.
(물론, num 변수 자체로 값 변경은 가능)
예시
#include <iostream>
using namespace std;
void sub_A(const int** a) // 읽기만 하겠다.
{
// **a = 10; 읽기만 할 수 있어서 오류
}
void sub_B(int* const* b)
{
int x = 10;
**b = 11; // 가르키는 대상을 바꾸는것은 가능
// *b = &x; // 다른 주소로 변경 불가
// 만약 **b = 10 조차 불가능하게 하려면 (const int * const *b)로 사용하면 됨
}
int main(void)
{
int n = 5, k = 6;
// 가르키는 대상을 읽기만 하겠다.
// 초기값 굳이 필요 x
const int* cp;
cp = &n;
cp = &k; // 다른 주소로 변경 가능
// *cp = 100; 값 변경은 불가
cout << *cp << endl; // 값을 읽는것은 가능
// 포인터를 고정하기 때문에 초기값 반드시 필요(n만을 가르키겠다)
// 가르키는 대상이 const 타입일 필요는 없다.
// 나중에 다른 변수의 주소 대입 불가 (q = &k;)
int* const q = &n;
sub_A(&cp);
sub_B(&q);
}
#define vs const
const는 타입 Error 등을 막을 수 있으며
가독성 측면에서도 #define 보다 괜찮은 편이다.
하지만 메모리를 잡아먹기 때문에 메모리 절약 측면에서는 #define이 나은 편
한편으로 #define은 런타임 중 값 확인 하기 까다롭기도 하다.
반응형
'프로그래밍 언어 > C 언어' 카테고리의 다른 글
[C/C++] [전처리기] #if (0) | 2024.07.23 |
---|---|
[C/C++] 열거형 타입 enum 이란? (3) | 2024.06.06 |
[C/C++] #ifdef, #if defined() 비교 및 활용 (0) | 2022.09.01 |
[C 전처리기] #error 활용 예제 (0) | 2022.08.11 |
[C/C++] memmove() 함수 사용과 예제 (0) | 2021.11.28 |
댓글