DSL 15장에 매크로를 설명한 게 있어 나중에 예로 들 때 이용하도록 정리해 놓는다.
옳은 예)
예를 들어 두 숫자의 최댓값을 구해야 하는 경우가 많다고 해보자. 그래서 a > b ? a : b와 같은 형식을 C 언어를 사용해 중복작성해야 한다고 해보자.
#define max(x, y) x > y ? x : y
int a=5, b=7, c=0;
c = max(a,b);
나쁜 예1 - 잘못된 확장
하지만 매크로를 사용하면 미묘한 문제가 수없이 생겨서 곤경에 빠지기도 한다. 매크로에 파라미터를 사용하면 특히 그렇다. 숫자를 제곱하는 매크로를 생각해보자.
#define sqr(x) x * x
int a=5, b=1, c=0;
c = sqr(a + b);
6의 2승인 36이 나올 것이라고 기대했지만, c의 값은 11이 되어 버린다. 매크로가 확장되면서 표현식이 a + b * a + b 로 만들어지기 때문이다. *연산자가 +연산자보다 우선순위가 높으므로, 이 표현식은 (a + b) * (a + b)가 아니라, a + (b*a) + b로 계산된다.
해결책1
이 문제를 피하려면, Lisp 개발자가 사용하는 개수보다 더 많은 괄호를 사용해서 아래와 같이 작성해야 한다.
#define betterSqr(x) ((x) * (x))
나쁜 예2 - 중복평가
#define max(x, y) x > y ? x : y
int a=5, b=1, c=0;
c = max(++a, ++b);
증가연산자(++)가 있는 경우 함수일 경우에는 max(6, 2)을 예상하고 6일 것이라고 예상이 되지만, 매크로의 경우 7이 결과로 나와버린다. 이 코드는 중복 평가가 발행하는 예다. 매크로 몸체에서 이 인자를 한 번 이상 사용할 때 결국 인자는 여러 번 평가되게 된다. 이 예제에서는 a와 b는 모두 두 번 증가한다.
나쁜 예3 - 변수점유
#define cappedTotal(input, cap, result) \
{int i, total = 0; \
for(i=0; i<5; i++) \
total = total + input[i];\
result = (total > cap) ? cap : total; }
int arr1[5] = {1, 2, 3, 4, 5};
int amount = 0;
cappedTotal(arr1, 10, amount);
int total = 0;
cappedTotal(arr1, 10, total);
하래 붉은 영역의 코드가 실행되면, total은 0이 된다. 괄호에 의해 스코프가 가려지기 때문이다.
'Languages > C++' 카테고리의 다른 글
별모양 찍기 : mvp 와 리팩토링 (0) | 2021.04.12 |
---|---|
소켓 프로그래밍 튜토리얼 at binarytides.com (0) | 2014.06.18 |
LLVM 컴파일러? (0) | 2013.10.09 |
V8 학습 (0) | 2013.09.12 |
C++ web framework like spring for Java (0) | 2013.03.11 |