함수형 매크로의 핵심 위험은 텍스트 치환과 중복 평가입니다.
MAX(i++, j++)같은 코드가 왜 위험한지 설명해야 한다- 매크로를 유지할지
static inline으로 바꿀지 판단이 필요하다 - 괄호를 붙였는데도 여전히 매크로가 불안한 이유를 확인하고 싶다
숏컷 코드
c
#define MAX(a, b) ((a) > (b) ? (a) : (b))
/* MAX(i++, j++) 는 위험 */문법
함수형 매크로는 함수 호출이 아니라 텍스트 치환입니다.
c
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int i = 1;
int j = 2;
int m = MAX(i++, j++);이 코드는 결국 아래처럼 여러 번 평가될 수 있습니다.
c
((i++) > (j++) ? (i++) : (j++))즉 값 자체보다 "몇 번 평가되는가"가 문제입니다.
선택 기준
계산 로직이면 대부분 static inline 쪽이 더 낫습니다.
c
static inline int max_int(int a, int b) {
return a > b ? a : b;
}이쪽이 더 나은 이유는:
- 타입 검사 가능
- 인자 한 번 평가
- 디버거에서 읽기 쉬움
체크포인트
- 계산 로직이면
static inline이 먼저입니다. - 매크로 인자에
i++, 함수 호출, 대입식 같은 부작용 표현식은 피합니다. - 괄호는 기본이지만 중복 평가 문제까지 해결해 주지는 않습니다.
- 조건부 컴파일,
#,##같은 전처리 전용 기능일 때 매크로가 남을 이유가 큽니다.
주의할 점
매크로는 타입이 다른 인자 조합도 조용히 받아들일 수 있어서, "잘 컴파일되는데 이상하게 동작하는" 버그를 만들기 쉽습니다. 계산이나 비교 로직을 매크로로 두는 건 편해 보여도 유지보수 비용이 큽니다.
참고 링크
2 sources