easy software

C언어 매크로 지시자 #define 과 매크로함수 그리고 전처리 본문

C언어/매크로와 전처리기(preprocessor)

C언어 매크로 지시자 #define 과 매크로함수 그리고 전처리

JAVA 웹개발자 2015. 2. 15. 00:43

C언어의 매크로 지시자 중 하나인 #define 을 알아보겠습니다.

 

매크로란 일종의 치환문입니다.

 

#define    PI    3.141597

 

위의 코드를 해석하면,

 

'PI가 소스코드상에서 보이면 무조건 3.141597 로 치환해라' 라고 해석합니다.

 

그리고 PI는 소스코드상에서 무조건 3.141597이 됩니다.

 

즉, 상수가 된거죠. 그러므로 보통 위와같은 정의를 '매크로상수' 라고 부릅니다.

 

*매크로를 사용할 떄에는 문장 끝에 ;(세미콜론)을 붙이지 않습니다.

 

컴파일러는 컴파일시에 매크로가 소스코드가 아니라고 판단하기 때문입니다.

 

그리고 매크로를 두 줄로 나누어서 작성할 때에는 \ 를 사용하여 줄을 바꿔줄 수 있습니다.

 

ex) #define    PI \

3.141597

 

 

 

#define    SQUARE(x)    x*x

 

위의 코드에서 SQUARE는 함수같지 않나요? 심지어 인자도 받을 수 있는거 같네요.

 

네. 매크로 함수라고 불리우는 녀석입니다.

 

실제로 괄호안의 x는 인자를 뜻합니다.

 

소스코드 상에서 SQUARE(2) 를 호출하면 2*2인 4를 반환해줍니다.

 

 

 

이제 매크로 함수에서 중요한 부분을 설명드려야 하는데요. 그 전에 전처리에 대해 알아야 합니다.

 

소스코드를 실행파일로 만들때는 컴파일과 링크의 과정을 거치게됩니다.

 

이 컴파일에서는 두 가지로 다시 나눌 수 있는데요, 바로 전처리와 컴파일입니다.

 

전처리는 말 그대로 전에 처리한다라는 뜻입니다. 즉, 컴파일 전에 일어나는 일입니다.

 

#define    PI    3.14

 

int main(void){

printf("%d \n", PI);

return 0;

}

 

위의 코드를 컴파일하면, 제일 먼저 전처리기가 전처리를 진행합니다.

 

그럼 아래와 같은 코드가 됩니다.

 

int main(void){

printf("%d \n", 3.14);

return 0;

}

 

보시다시피, 전처리가 끝나고 나면 매크로 지시자인 #define이 사라지고,

 

printf함수의 인자에서 PI 대신에 3.14가 있음을 알 수있습니다.

 

이런 치환과정이 전처리입니다.

 

 

이제 매크로 함수에서 중요한 부분을 공부해 봅시다.

 

#define    SQUARE(x)    x*x

 

int main(void){

int a;

 

printf("정수입력 \n"):

scanf("%d", &a);

 

printf("계산결과 : %d \n", SQUARE(a+3));

return 0;

}

 

위와 같이 코드가 작성되어있습니다.

 

이제 사용자가 3을 입력하면 어떤 결과가 나올까요?

 

출력결과 : 15

 

결과는 이상하게 15가 나옵니다.

 

사용자가 3을 입력했으면, (3+3) * (3+3) = 36이 나와야 정상아닌가요?

 

그런데 매크로는 앞서서 치환을 한다고 말씀드렸습니다.

 

즉, 매크로함수를 호출하면 아래와 같이 계산됩니다.

 

a + 3 * a + 3 => a + 3a + 3 => 3 + 9 + 3 => 15

 

처음에 x*x패턴을 충족해야 하기때문에, a+3 * a+3이 됩니다.

 

이후에 곱셈이 먼저 진행되고 덧셈이 진행되면서 위와같은 수식이 성립됩니다.

 

 

 

그럼 위와 같은 문제를 해결하기 위해서 어떻게 해야 할까요?

 

공식화 되어 사용하는 문법이 있습니다.

 

즉, 매크로를 정의할때 모든 인자에 괄호를 씌워주는 것이죠.

 

#define    SQUARE(x)    ((x)*(x))

 

위의 코드에서 매크로를 이렇게 바꾸어서 실행하면 아래와 같은 수식이 성립됩니다.

 

((a+3) * (a+3)) => (6) * (6) => 36

 

매크로를 사용하실 때에는 괄호를 잊지마시기 바랍니다.

Comments