정적코드분석/코딩표준

C/C++ 언어 매크로 사용의 위험성-1편:타입

몇몇 코딩 스탠다드(JSF C++ 등)에서는 #define을 이용한 C/C++ 언어 매크로 사용을 금지합니다. 대신 인라인 함수(Inline Function) 를 사용할 것을 권하고 있습니다. 왜일까요?

C/C++ 언어 매크로

#define 으로 정의된 매크로는 컴파일 과정에서 정의한 문자열로 치환된다는 것을 익히 알고 있을것입니다. 예를 들어, 아래 매크로를 보겠습니다.

 #define MAX(a,b) a < b ? a : b

코드에서 아래와 같이 사용했다면,

int x = MAX(a, b);

해당 코드는 컴파일러의 전처리를 거쳐 아래와 같은 구문으로 바뀝니다.

int x = a < b? a: b;

위 매크로처럼 인자를 가진 매크로는 흔히 간단한 연산을 수행할때 많이 사용합니다. 그래서 흔히 ‘매크로 함수’라고 부릅니다. 하지만 매크로 함수는 함수가 아닙니다. 바로 타입 검사를 안한다는 사실이지요. 아래 프로그램에서 확인해보겠습니다.

#define MAX(a,b) a < b ? a : b

int main()
{
  const char *v1 = MAX("foo","bar");
? return 0;
}

매크로의 인자를 문자열로 넣었습니다. 물론 문자열끼리 저런식으로 비교하지는 않죠. 말도 안되는 코드 입니다. 그럼 위 코드를 g++ 4.7.2로 컴파일 해보겠습니다.

$?g++ -o macro_test?macro_test.cpp
$

??????!!!! ?말도 안되는 비교인데 어찌되었던 수행이 됩니다. 타입 체킹을 안하기 때문입니다.

대신 인라인 함수를 사용할 것!

반면, 인라인 함수는 매크로와 달리 (당연히) 타입 검사를 하지요. 다음의 소스코드를 살펴보겠습니다.

#define MAX(a,b) a > b ? a : b
int max(int a, int b) {return a > b ? a : b;}

int main()
{
 const char *v2 = max("foo", "bar");
 return 0;
}

이를 수행시키면 아래와 같은 결과 나옵니다.

$ g++ -o m1 m1.cpp
m1.cpp: In function 'int main()':
m1.cpp:6:37: error: invalid conversion from 'const char*' to 'int' [-fpermissive]
m1.cpp:2:5: error: initializing argument 1 of 'int max(int, int)' [-fpermissive]
m1.cpp:6:37: error: invalid conversion from 'const char*' to 'int' [-fpermissive]
m1.cpp:2:5: error: initializing argument 2 of 'int max(int, int)' [-fpermissive]
m1.cpp:6:37: error: invalid conversion from 'int' to 'const char*' [-fpermissive]

같은 일을 하더라도 매크로는 타입검사를 하지 않는 반면, 인라인 함수는 타입 검사를 수행하기 때문에 좀 더 안전한 코드를 만들 수 있습니다.

Leave a Reply

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *