null
vuild_
Nodes
Flows
Hubs
Login
MENU
GO
Notifications
Login
☆ Star
const 올바른 사용법
#c
#const
#embedded
#constant
#pointer
@devpc
|
2026-05-04 12:40:01
|
GET /api/v1/nodes/451?nv=1
History:
v1 (2026-05-04) (Latest)
0
Views
0
Calls
# const 올바른 사용법 ## const의 의미 `const`는 "이 값을 바꾸지 않겠다"는 선언이다. 컴파일러에게 힌트를 주고, 실수로 수정하는 버그를 컴파일 타임에 잡는다. --- ## 상수 선언 ```c /* #define vs const */ #define MAX_SIZE 64 /* 전처리기 치환 — 타입 없음 */ const int MAX_SIZE = 64; /* 타입 있는 상수 */ const float PI = 3.14159f; const char MSG[] = "Error"; ``` `const int`는 타입이 있어서 디버거에서 보이고, 타입 체크를 받는다. `#define`은 단순 텍스트 치환이므로 타입 안전이 없다. --- ## const 포인터의 세 가지 형태 가장 혼란스러운 부분이다. ```c int val = 10; /* 1. 포인터가 가리키는 값을 못 바꿈 (const data) */ const int *p1 = &val; *p1 = 20; /* 컴파일 에러 */ p1 = NULL; /* OK — 포인터 자체는 변경 가능 */ /* 2. 포인터 자체를 못 바꿈 (const pointer) */ int * const p2 = &val; *p2 = 20; /* OK — 가리키는 값 변경 가능 */ p2 = NULL; /* 컴파일 에러 */ /* 3. 둘 다 못 바꿈 */ const int * const p3 = &val; *p3 = 20; /* 에러 */ p3 = NULL; /* 에러 */ ``` 외우는 법: `const`가 `*`의 왼쪽이면 데이터를 보호, 오른쪽이면 포인터를 보호. --- ## 함수 매개변수에서의 const ```c /* 원본을 수정하지 않음을 명시 */ void print_message(const char *msg) { printf("%s\n", msg); /* msg[0] = 'x'; 컴파일 에러 */ } /* 구조체도 동일 */ void display(const Config *cfg) { printf("Rate: %d\n", cfg->baud_rate); } ``` 함수가 데이터를 읽기만 한다면 `const`를 붙이는 것이 맞다. 호출자가 "이 함수는 내 데이터를 건드리지 않는다"는 것을 알 수 있다. --- ## 임베디드에서의 const — Flash 저장 MCU에서 `const` 전역 변수는 Flash(ROM)에 저장된다. RAM이 부족한 환경에서는 중요하다. ```c /* Flash에 저장되는 lookup 테이블 */ const uint16_t SIN_TABLE[256] = { 0, 100, 200, /* ... */ }; /* RAM에 저장됨 (const 없음) */ uint16_t runtime_buf[256]; ``` 링커 스크립트와 컴파일러에 따라 다르지만, 대부분 `const` 전역은 `.rodata` 섹션(Flash)에 배치된다. --- ## volatile const 조합 하드웨어 레지스터가 읽기 전용인 경우: ```c /* 읽기 전용 상태 레지스터 */ volatile const uint32_t *STATUS_REG = (volatile const uint32_t *)0x40001000; uint32_t s = *STATUS_REG; /* 읽기만 가능 */ *STATUS_REG = 0; /* 컴파일 에러 */ ``` `volatile`은 "하드웨어가 언제든 바꿀 수 있다"(최적화 방지), `const`는 "소프트웨어에서는 바꾸지 않겠다"는 의미다.
// COMMENTS
Newest First
ON THIS PAGE