상수는 프로그램에서 값이 변하지 않는 데이터를 의미한다.
이는 리터럴 상수와 심볼릭 상수로 구분할 수 있다.
📌 1. 리터럴(Literal) 상수
int num = 30 + 40;
- 여기서 30, 40은 이름이 없는 고정된 값 → 리터럴 상수
- 프로그램 코드에 직접 숫자, 문자, 문자열, 실수 등을 쓰는 방식
🔹 특징
- 자료형은 컴파일러가 자동으로 적절히 부여 (예: 30 → int, 30.0 → double)
- 컴파일 시 메모리에 저장될 수 있다. (상수 풀, 읽기 전용 메모리 등)
📌 2. 심볼릭(Symbolic) 상수
이름이 있는 상수.
변수처럼 보이지만, 값을 바꿀 수 없다.
C에서는 다음 2가지 방법으로 심볼릭 상수를 선언한다:
- const 키워드를 이용한 상수
- #define을 이용한 매크로 상수
✅ const 상수
const int MAX = 100;
const를 붙이면 변경이 불가능한 변수가 된다.
이는 변수처럼 보이지만, 컴파일러가 수정하지 못하게 막는다.
📍 const 전역 상수
const int x = 5;
- 데이터 영역의 read-only 영역에 저장됨
- 하드웨어/OS에서 실제 보호되는 메모리 영역에 할당됨
- 수정 시 런타임 에러 또는 예외 발생 가능
📍 const 지역 상수 (ex. 함수 내부 또는 파라미터)
void func(const int y) {
// y = 10; // ❌ 컴파일 에러
}
- 스택 영역에 저장
- 컴파일러가 논리적으로 수정 금지
- 하지만 포인터로 강제 접근하면 수정 가능(UB)
🔬 예제 코드
#include <stdio.h>
const int x = 5;
void globalMod() {
int* p = (int*)&x;
*p = 100;
printf("global: %d\\n", x);
}
void localMod() {
const int y = 5;
int* p = (int*)&y;
*p = 100;
printf("local: %d\\n", y);
}
- globalMod() 호출 시 → 보통 런타임 에러 발생
- localMod() 호출 시 → 실행되지만 Undefined Behavior
🔥 전역 const는 실제 읽기 전용 메모리, 지역 const는 논리적인 제한만 있을 뿐 실제 보호는 안 된다.
✅ 매크로 상수 (#define)
#define PI 3.141592
- 전처리기(preprocessor)에 의해 컴파일 전 텍스트 치환
- 변수처럼 동작하지 않음 → 자료형 없음, 메모리 없음
- 디버깅이 어렵고 타입 안정성 없음 → 가능한 const 사용 권장
✅ const vs #define 비교
항목 | const | #define |
자료형 | 있음 (int, float 등) | 없음 (그냥 텍스트) |
컴파일 단계 | 컴파일 시 처리 | 전처리 시 치환 |
디버깅 시 식별 가능 | ✅ 가능 | ❌ 불가능 (치환됨) |
메모리 사용 | 변수처럼 존재 | 메모리 없음 |
범위(scope) | 지역/전역 | 전체 파일 |
추천 여부 | ✅ 타입 안전 & 유지 보수 쉬움 | ⚠️ 간단한 상수 정의에만 사용 추천 |
🧠 마무리 요약
상수 종류 | 설명 |
리터럴 상수 | 이름 없이 코드에 직접 쓰는 고정 값 (10, 'A', "abc") |
const 상수 | 이름 있는 상수, 메모리 존재, 타입 안전 |
매크로 상수 | 전처리기에 의해 단순 치환, 메모리/타입 없음 |
'프로그래밍 언어 > C' 카테고리의 다른 글
06. 구조체 (Struct) (0) | 2025.06.30 |
---|---|
05. 함수 포인터 (Function pointer)와 void 포인터 (0) | 2025.06.27 |
04. 포인터와 문자열 (2) | 2025.06.26 |
03. 자료형 변환 (Type casting) (0) | 2025.06.24 |
01. 실수 표현 (고정 소수점과 부동 소수점) (0) | 2025.03.31 |