C++ Macro Programming | "매크로 프로그래밍" 가이드

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 |