2015년 5월 1일 금요일

C++ 의 매크로 함수

 이전에 #define문을 이용한 상수의 정의를 살펴보았는데 이번에는 매크로(macro)를 정의하는 방법에 대해서 알아보겠다. 매크로는 함수와 외형 및 동작하는 방식이 비슷해 보이지만 내부적으로는 크게 다른 방식으로 동작한다.

 매크로는 #define문으로 정의되는데 프로그램 중간에서 정의된 이름을 만나면 해당하는 매크로 코드로 치환된다. 예를 들어서 다음과 같이 매크로를 정의한다.

#define pow3(x) x*x*x

이제 프로그램 중간에 pow3(2) 라고 쓰면 그 명령어가 통채로 2*2*2으로 대체되게 된다. 만약 pow(iA)라고 쓰면 iA*iA*iA로 바뀐다. 외형상 2이라는 숫자나 iA와 같은 변수를 매크로에 x로 인자로 넘길 수 있게 되므로 마치 함수 같아 보이지만 동작 방식은 전혀 다른 것이다.

#include <stdio.h>
#define pow3(x) x*x*x

int main() {
   int iA = 5;
   float fA = 1.5;
   printf("%d**3 = %d \n", 6, pow3(6)); //❶
   printf("%d**3 = %d \n", iA, pow3(iA)); //❷
   printf("%f**3 = %f \n", fA, pow3(fA)); //❸
}
6**3 = 216
5**3 = 125
1.500000**3 = 3.375000

여기서 ❶, ❷, ❸번 줄을 보면 매크로를 마치 함수를 호출하듯이 사용하고 있으나, 사실은 컴파일하기 전에 프로그램을 다음과 같이 단순 치환하여 변형한 것이 불과하다.

printf("%d^3 = %d \n", 6, 6*6*6 );
printf("%d^3 = %d \n", iA, iA*iA*iA );
printf("%f^3 = %f \n", fA, fA*fA*fA );

따라서 함수의 호출과는 동작하는 방식이 전혀 다른 것이다.

 매크로의 인수로는 두 개 이상도 사용가능하다. 다음 예는 두 수들 중에서 작은 수를 찾아주는 매크로이다.

#include <stdio.h>
#define MIN(a, b) (a<b)? a:b
int main() {
   short nA = -10, nB = -15;
   printf("MIN(%d,%d) is %d.\n", 2, 3, MIN(2,3));
   printf("MIN(%d,%d) is %d.\n", nA, nB, MIN(nA, nB));
}
MIN(2,3) is 2.
MIN(-10,-15) is -15.

 매크로는 단순치환이기 때문에 다음과 같은 경우를 주의해야 한다. 다음 예에서 세 숫자의 곱으로 치환하는 매크로를 예로 들어보았다.

#include <stdio.h>
#define MUL1(a,b,c) a*b*c //❶
#define MUL2(a,b,c) (a)*(b)*(c) //❷
int mulF(int, int, int);

int main(void)
{
   short sA = 2, sB = 3, sC = 4, sD1, sD2, sDF;
   sD1 = MUL1(sA+1, sB, sC);//❸
   sD2 = MUL2(sA+1, sB, sC);//❹
   sDF = mulF(sA+1, sB, sC);
   printf("MUL1: %d*%d*%d = %d \n", sA+1, sB, sC, sD1);
   printf("MUL2: %d*%d*%d = %d \n", sA+1, sB, sC, sD2);
   printf("MulF: %d*%d*%d = %d \n", sA+1, sB, sC, sDF);
}

int mulF(int iA, int iB, int iC)
{
   return iA*iB*iC;
}

❶과 같이 매크로를 정의했다면 ❸은 다음과 같이 치환된다.


nD1 = nA+1 * nB * nC;

따라서 의도하지 않은 엉뚱한 계산결과가 nD1변수에 저장되게 된다. 즉, 매크로는 정의된 그대로 치환을 하기 때문에 이와 같은 오류가 발생하는 것이다. 이를 방지하려면 ❷와 같이 각각의 인수에 괄호( )를 쳐주면 된다. 그러면 ❹는 다음과 같이 의도한 대로 치환된다.

nD2 = (nA+1) * (nB) * (nC);

이로서 의도한 계산 결과를 얻을 수 있다. 전체 실행 결과는 다음과 같다.

MUL1: 3*3*4 = 14
MUL2: 3*3*4 = 36
MulF: 3*3*4 = 36

매크로는 함수로 작성하기에는 다소 간단한 기능을 구현하는데 자주 사용된다. 하지만 매크로를 사용할 때에는 위와 같이 문제가 발생할 소지가 있으므로 보통 인수로 사용하는 변수에는 괄호를 꼭 붙여서 사용해야함에 주의해야 한다.


댓글 없음:

댓글 쓰기