#define — 이는 전처리 지시문으로, 컴파일 이전에 모든 식별자의 인스턴스를 값으로 치환합니다. 이는 변수를 생성하지 않으며, 타입, 경계를 인식하지 않고, 범위를 고려하지 않습니다.
const — 이는 실제 변수를 생성하지만 초기화 이후에는 쓰기가 차단된 한정자입니다. const 변수는 타입이 있으며, 범위가 있고, 디버깅에 참여하며 더 안전할 수 있습니다. 이러한 변수는 .rodata 세그먼트나 스택/메모리에 배치됩니다.
#define — 컴파일 단계에서 필요한 단순 스칼라 값에 대해, 특히 전처리 조건이나 배열 크기(#define SIZE 16)에 사용할 경우.const — 타입 안전하게 전달하고 디버깅하며 안전하게 내보내야 하는 값에 대해 (헤더 파일, 모듈 간).const를 사용하는 것이 바람직합니다.예시:
#define PI 3.14159 const double G = 9.81; int arr[PI]; // 오류! PI가 정수 아님 int arr2[G]; // 오류! G가 컴파일 시간 값이 아님
질문: const int a = 10;가 배열을 만들기 위한 컴파일 시간 상수처럼 작동합니까?: int arr[a];?
답변: 아닙니다. C 언어에서 const는 한정자이지만, 변수는 실행 시간에 생성되고 초기화되므로 배열의 크기는 리터럴이나 컴파일러가 알고 있는 표현이어야 합니다. #define을 사용하거나 enum { SIZE = 10 };을 사용해야 합니다.
오류 예시:
const int a = 5; int arr[a]; // C89/90에서는 작동하지 않음 (VLA는 C99에서 도입되었지만, 모두 지원되지는 않음)
역사
미디어 서버에서 버퍼 크기를 설정하기 위해
const int를 사용하려고 시도했으나, "컴파일 시간 상수"라고 생각했습니다. 한 컴파일러(GCC, C99)에서는 모두 잘 작동했지만 대부분에서는 컴파일 오류가 발생하여(VLA가 지원되지 않음) 긴급하게 #define으로 재작성했습니다.
역사
플랫폼 종속 코드에서
#define NAME "MyApp"로 문자열을 정의하고 여러 곳에서 사용했지만 괄호를 잊어버렸습니다. 문자열에 명시적인 괄호 없이 문자를 추가하면 잘못된 결과가 발생하여 로그에 이상한 버그가 발생했습니다.
역사
여러 모듈이 있는 프로젝트에서 #define을 사용하여 두 군데에서 다른 값으로 상수를 정의했습니다(복사-붙여넣기). 결과적으로 모듈은 서로 다른 상수와 작업하게 되었고, 데이터 비완전성이 발생하였으며 이를 철저한 디버깅으로 수정했습니다.