|

C 언어 define const 차이: #define과 const는 왜 다를까

C 언어 #define const 차이 상수 사용 기준 대표 이미지
#define과 const는 둘 다 상수처럼 보이지만 컴파일 전에 처리되는 위치와 타입 정보가 다릅니다.

#define const 차이는 C 언어에서 상수를 만들 때 가장 먼저 헷갈리는 지점입니다. 둘 다 값을 바꾸지 않는 것처럼 보이지만, 실제로는 코드가 처리되는 단계와 타입 정보가 다릅니다.

핵심은 #define은 전처리기의 텍스트 치환이고, const는 타입을 가진 이름 있는 값이라는 점입니다. 이 글은 C 전처리기, const qualifier, enum 규칙을 기준으로 사용 기준을 정리합니다.

C 언어 #define과 const 차이 요약 카드
#define은 전처리 치환, const는 타입을 가진 읽기 전용 객체에 가깝습니다.

#define const 차이를 먼저 한 줄로 정리하면

`#define`은 전처리 단계에서 이름을 다른 토큰으로 바꾸는 규칙입니다. `const`는 타입을 가진 객체에 읽기 전용 성격을 붙이는 방식입니다.

#define MAX_COUNT 10

const int max_count = 10;

겉으로는 둘 다 `10`이라는 값을 이름으로 부르는 것처럼 보입니다. 하지만 `MAX_COUNT`는 컴파일러가 타입을 검사하기 전에 치환되고, `max_count`는 `int` 타입을 가진 이름 있는 객체로 남습니다.

#define은 전처리 치환이다

전처리기는 컴파일 전에 소스의 토큰을 바꿉니다. 그래서 `#define`으로 만든 이름은 타입을 갖는 변수가 아니라 코드 조각에 가깝습니다.

#define SQUARE(x) x * x

int result = SQUARE(1 + 2);  // 1 + 2 * 1 + 2

이 예제는 매크로가 함수처럼 보이지만 실제로는 텍스트 치환이라는 점을 보여줍니다. 괄호를 잘 넣지 않으면 기대와 다른 식이 만들어질 수 있습니다.

const는 타입을 가진 이름이다

`const int max_count = 10;`은 `int` 타입의 값을 만들고, 그 값을 해당 이름을 통해 수정하지 못하게 합니다. 컴파일러는 타입 정보를 알고 있으므로 잘못된 대입이나 인자 전달을 더 잘 검사할 수 있습니다.

const int max_count = 10;

// max_count = 20;  // 오류: const 객체를 수정하려고 함

void print_count(int count) {
    printf("%d\n", count);
}

print_count(max_count);

상수처럼 보이는 값을 코드 안에서 의미 있게 다루고 싶다면 `const`가 더 읽기 쉬운 경우가 많습니다.

배열 크기에서는 상황이 달라질 수 있다

C에서는 컴파일 시점 상수가 필요한 문맥과 런타임 객체가 허용되는 문맥이 다릅니다. 그래서 오래된 C 코드나 특정 컴파일 옵션에서는 배열 크기에 `#define` 또는 `enum` 상수를 쓰는 경우가 많습니다.

#define BUFFER_SIZE 256

char buffer[BUFFER_SIZE];

이 부분은 C 표준 버전과 컴파일러 옵션에 따라 체감이 달라질 수 있습니다. 블로그 글에서는 `const`가 모든 문맥에서 매크로 상수를 완전히 대체한다고 단정하지 않는 것이 안전합니다.

정수 상수 묶음은 enum도 후보가 된다

서로 관련 있는 정수 상수 여러 개를 표현한다면 `enum`이 더 자연스러울 수 있습니다. 이름 있는 값의 집합이라는 의도가 잘 드러나기 때문입니다.

enum Direction {
    DIR_UP,
    DIR_DOWN,
    DIR_LEFT,
    DIR_RIGHT
};

언제 무엇을 쓰면 좋을까

  • 단순 전처리 조건이나 include guard에는 `#define`이 자연스럽다
  • 타입이 있는 상수 값에는 `const`를 우선 고려한다
  • 관련 있는 정수 상수 집합은 `enum`을 고려한다
  • 함수처럼 보이는 매크로는 괄호와 부작용을 특히 조심한다

실무 체크리스트

  1. 이 이름이 컴파일 전 치환이어야 하는지 확인한다
  2. 타입 검사를 받는 값으로 남아도 되는지 본다
  3. 디버깅할 때 이름이 남는 편이 유리한지 생각한다
  4. 매크로 인자에 `i++` 같은 부작용이 들어갈 가능성을 피한다
  5. 정수 상수 묶음이면 enum이 더 읽기 쉬운지 검토한다

정리

C 언어에서 `#define`과 `const`는 모두 상수처럼 쓰일 수 있지만 역할이 다릅니다. `#define`은 전처리 치환이고, `const`는 타입을 가진 읽기 전용 이름입니다.

C 언어 기초 흐름은 C 언어 scanf fgets 차이, C 점 연산자 화살표 연산자 차이, C 언어 struct와 typedef 차이와 함께 보면 좋습니다. 외부 기준은 cppreference – Replacing text macros, cppreference – const type qualifier, cppreference – Enumerations를 확인했습니다.

함께보면 좋은 글