C++ Macro Programming | "매크로 프로그래밍" 가이드
이 글의 핵심
C++ Macro Programming에 대해 정리한 개발 블로그 글입니다. #define MAX 100 int arr[MAX];
매크로란?
텍스트 치환 메커니즘
#define MAX 100
int arr[MAX]; // int arr[100];
#define SQUARE(x) ((x) * (x))
int result = SQUARE(5); // ((5) * (5))
기본 매크로
// 상수 매크로
#define PI 3.14159
#define MAX_SIZE 1024
// 함수형 매크로
#define ABS(x) ((x) < 0 ? -(x) : (x))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) < (b) ? (a) : (b))
실전 예시
예시 1: 디버그 매크로
#ifdef DEBUG
#define LOG(x) std::cout << "[DEBUG] " << __FILE__ << ":" << __LINE__ << " " << x << std::endl
#define ASSERT(cond) if (!(cond)) { std::cerr << "Assertion failed: " << #cond << std::endl; abort(); }
#else
#define LOG(x)
#define ASSERT(cond)
#endif
int main() {
LOG("프로그램 시작");
int x = 10;
ASSERT(x > 0);
}
예시 2: 가변 인자 매크로
// C++11
#define PRINT(...) printf(__VA_ARGS__)
#define LOG(fmt, ...) printf("[LOG] " fmt "\n", ##__VA_ARGS__)
int main() {
PRINT("Hello %s\n", "World");
LOG("Value: %d", 42);
LOG("No args");
}
예시 3: 문자열화와 연결
// 문자열화
#define STRINGIFY(x) #x
#define TO_STRING(x) STRINGIFY(x)
// 토큰 연결
#define CONCAT(a,b) a##b
int main() {
std::cout << STRINGIFY(Hello) << std::endl; // "Hello"
std::cout << TO_STRING(100) << std::endl; // "100"
int xy = 10;
int result = CONCAT(x, y); // xy
}
예시 4: 반복 매크로
#define REPEAT_3(x) x x x
#define REPEAT_5(x) x x x x x
int main() {
REPEAT_3(std::cout << "Hello\n";)
// std::cout << "Hello\n"; std::cout << "Hello\n"; std::cout << "Hello\n";
}
고급 기법
// 1. X-Macro
#define COLOR_TABLE \
X(RED, 0xFF0000) \
X(GREEN, 0x00FF00) \
X(BLUE, 0x0000FF)
enum Color {
#define X(name, value) name,
COLOR_TABLE
#undef X
};
const char* colorNames[] = {
#define X(name, value) #name,
COLOR_TABLE
#undef X
};
// 2. 조건부 매크로
#if __cplusplus >= 201703L
#define NODISCARD [[nodiscard]]
#else
#define NODISCARD
#endif
NODISCARD int getValue();
자주 발생하는 문제
문제 1: 괄호 누락
// ❌ 괄호 없음
#define SQUARE(x) x * x
int result = SQUARE(1 + 2); // 1 + 2 * 1 + 2 = 5
// ✅ 괄호 추가
#define SQUARE(x) ((x) * (x))
int result = SQUARE(1 + 2); // 9
문제 2: 부작용
// ❌ 부작용
#define MAX(a,b) ((a) > (b) ? (a) : (b))
int x = 5;
int result = MAX(x++, 10); // x가 두 번 증가
// ✅ 함수 사용
template<typename T>
T max(T a, T b) {
return a > b ? a : b;
}
문제 3: 타입 안전성
// ❌ 타입 체크 없음
#define ADD(a,b) ((a) + (b))
int result = ADD("hello", "world"); // 컴파일 에러
// ✅ 템플릿 함수
template<typename T>
T add(T a, T b) {
return a + b;
}
문제 4: 디버깅 어려움
// ❌ 디버깅 어려움
#define COMPLEX_MACRO(x) \
do { \
int temp = (x); \
temp = temp * 2; \
result = temp + 1; \
} while(0)
// ✅ 함수 사용
int complexFunction(int x) {
int temp = x;
temp = temp * 2;
return temp + 1;
}
매크로 vs 대안
// 1. 상수 → constexpr
#define MAX 100
constexpr int MAX = 100; // ✅
// 2. 함수 → inline/template
#define SQUARE(x) ((x)*(x))
template<typename T>
inline T square(T x) { return x * x; } // ✅
// 3. 타입 → using
#define IntVector std::vector<int>
using IntVector = std::vector<int>; // ✅
유용한 매크로
// 1. 배열 크기
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
// 2. 오프셋
#define OFFSET_OF(type, member) ((size_t)&((type*)0)->member)
// 3. 범위 체크
#define IN_RANGE(x, min, max) ((x) >= (min) && (x) <= (max))
// 4. 비트 조작
#define SET_BIT(x, bit) ((x) |= (1 << (bit)))
#define CLEAR_BIT(x, bit) ((x) &= ~(1 << (bit)))
#define TOGGLE_BIT(x, bit) ((x) ^= (1 << (bit)))
FAQ
Q1: 매크로는 언제?
A:
- 조건부 컴파일
- 플랫폼별 코드
- 레거시 코드
Q2: 매크로 vs 함수?
A:
- 매크로: 전처리, 빠름
- 함수: 타입 안전, 디버깅
Q3: 가변 인자는?
A: __VA_ARGS__ 사용 (C++11)
Q4: 매크로 디버깅?
A: g++ -E 로 전처리 결과 확인
Q5: 모던 C++ 대안은?
A:
- constexpr
- template
- inline
Q6: 매크로 학습 리소스는?
A:
- “C++ Primer”
- GCC 문서
- “C Preprocessor”
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- C++ 전처리기 | “매크로” 고급 기법
- C++ Preprocessor Directives | “전처리 지시자” 가이드
- C++ Compilation Process | “컴파일 과정” 가이드
관련 글
- C++ 전처리기 |
- C++ 전처리기 완벽 가이드 | #define·#ifdef
- C++ Command Pattern 완벽 가이드 | 실행 취소와 매크로 시스템
- C++ Compilation Process |
- C++ Preprocessor Directives |