본문 바로가기

프로그래밍/C

[C]매크로와 매크로 함수 - 1

들어가며

매크로란 무엇일까.

게임을 자주 해본 사람이나 접해본 사람들은 매크로를 다음과 같이 이해하는 경우가 많다.

"매크로는 자동사냥 같은 거 말하는 거 아냐?"

그것에 관한 것은 잘 모르겠고, 나는 프로그래밍에 관해서 얘기할 예정이다.

 

매크로(Macro)

  • #define (매크로 이름) (설정할 값)

먼저 쉽게 말하자면 #define 지시자를 사용하여 값을 다른 이름으로 정의한다.

이름을 정하는 방법은 변수와 동일하며, 관습적으로 매크로의 이름은 대문자를 사용한다.

뭔소린지 모르겠다고? 나도 그렇다. 함께 알아보는 시간을 오붓하게 갖도록 하자.

 

사직서의 활용

자 다음의 코드를 보자.

int Damage(int atk)
{
    if(100<atk)
    	return 100;
    else
    	return 100;
        
    ......
}

일단 대충 게임이라고 가정하고 대충 끼워맞춰 보았다.

아직 코딩 실력이 미숙해서 그렇다. 아니꼽다면 한 3년 정도 기다리시던가 알아서 하시는 것을 권고드린다.

각설하고, 저 코드가 의도하는 바는 일단 어떤 피해를 가하더라도 100의 피해만 받는 그런 코드다.

저 코드에서 좀 주요하게 반복되는 수치들이 있는데 설마 100일 것 같은가?

그렇다!

만약 저 100이라는 수치가 생각보다 함수 내부에 훨씬 많이 있다고 가정하자.

그리고 모종의 이유로 저 100의 수치를 조정해야 할 상황이 발생했다.

그렇다면 본인이 그 수치를 조정해야하는 담당자라고 가정했을 때, 설마 코드 내부에 있는 수치 하나하나 숫자를 바꿔야 하는가?

그렇게 된다면 상당히 귀찮고, 잘 못 기입할 확률도 높고, 다른 수치와 헷갈릴 수도 있고, 여러모로 사직서가 마려워지지 않는가?

사실 현업에서 그짓을 하고 있다면 상사가 먼저 사직서를 양손에 꼭 쥐어주지 않을까.

만약 '어쩔 수 없지' 라고 생각했다면 지금 당장 나처럼 책 피고 코딩 공부를 처음부터 다시 시작하길 권고한다.

 

매크로의 활용

#define FXD_DMG 100

int Damage(int atk)
{
	if(FXD_DMG < atk)
    	return FXD_DMG;
    else
    	return FXD_DMG;
    ......
}

자, 위 코드에서 헤더의 밑부분에 'FXD_DMG(fixed_damage, 고정 피해량)'이라는 '매크로'를 추가한 모습이다.

지금 본인이 의미하고자 하는 수치들의 사용의도를 드러내어 코드가 좀 더 명확해졌다.

또한 '고정 피해량'을 수정해야 할 경우에는 매크로에 있는 값만 수정하면 되므로 아주 게을러질 수 있지 않은가?

역시 머리가 좋지않으면 몸이 고생한다는 말은 정확하게 시대를 관통하고 있다.

이 똥글을 보고 있는 여러분 또한 열심히 공부하고 아주아주 게으른 프로그래머가 되길 바란다.

 

#define의 매커니즘

'#define'은 컴파일 직전에 처리된다.

전처리기 과정을 거치면 'FXD_DMG'는 100으로 변환된다.

변환된 코드는 전처리기 과정 때 임시로 생성될 뿐, 원본 코드에는 전혀 영향을 주지 않으니 아직 몸이 고생하고 있는 나와 독자들은 걱정하지 않아도 된다.

쉽게 말해서, 컴퓨터는 'FXD_DMG라는 것을 보면 전부 '100'으로 인식해버리겠다!' 라는 뜻이다.

이것도 이해하지 못 했다면 몸 뿐만 아니라 머리, 마음도 아프고 고생하는 것이 분명하니 다시 태어나는 것을 권고한다.

 

매크로의 매크로

#define으로 정의한 매크로는 다른 이름으로 다시 정의할 수 있다.

#define FXD_DMG 100
#define MIN_DMG FXD_DMG   // 값은 100이다.
#define MAX_DMG FXD_DMG   // 이 또한 100이다.

결과적으로 MIN_DMG와 MAX_DMG는 둘 다 100의 값을 의미한다.

어디다가 쓸 지는 아직 감이 안 잡히지만, 알아놓으면 언젠가 사용할 상황이 있다면 사용하지 않겠는가.

오늘도 지식이 늘었다.

 

매크로의 해제

매크로를 설정했다면 해제도 할 수 있지 않겠는가?

  • #undef (매크로 이름)
#define FXD_DMG 100

int Damage(int atk)
{
	if(FXD_DMG < atk)
    	return FXD_DMG;
    else
    {
        #undef FXD_DMG		// 고정 피해량 매크로를 해제
        #define FXD_DMG 0	// 다시 0을 고정 피해량으로 정의
    	return FXD_DMG;
    }
    ......
}

이제 이 코드는 100이하의 피해는 받지 않는 코드가 되었다고 볼 수 있다.

#define으로 정의한 매크로를 해제하고 싶다면 #undef에 매크로 이름을 지정해주면 간단히 매크로를 해제할 수 있다.

만약 해제된 매크로를 계속해서 사용한다면 컴파일 에러가 발생하는 것 쯤은 아무리 몸이 고생한다고 해도 예상할 수 있을 것이다.

 


 

매크로 함수

이번에는 매크로 함수에 관하여 간단하게 고찰해보자.

#define은 함수 모양으로도 정의할 수 있다.

  • #define (매크로 이름)(인자) (함수)(인자)
  • #define (매크로 이름)(인자) (코드 조합)
#define INFO_DMG(x) printf("적에게 %d의 피해를 입힙니다.\n", x)

int main()
{
    INFO_DMG(150);
    INFO_DMG(263);
    
    return 0;
}

#define으로 함수 모양의 매크로를 정의할 때는 소괄호 내부에 자료형은 생략하고 인수의 이름만 지정하면 된다.

그리고 호출할 함수를 작성한 뒤 매크로에 지정했던 인수를 그대로 함수 안에 넣으면 된다.

즉, #define INFO_DMG(x)에서 'x'는,

printf("적에게 %d의 피해를 입힙니다.\n", x)의 'x'로 전달된다.

 

매크로 함수의 메커니즘

우린 방금 매크로의 메커니즘에 대해 배웠지 않는가?

매크로 함수도 결국 매크로의 함수 형태이므로 작동원리 또한 동일하게 굴러간다.

전처리기 과정을 거치면 'INFO_DMG(150)' 은 'printf("적에게 %d의 피해를 입힙니다.\n", 150)' 로 바뀌는 것 쯤은 이 글을 읽고 있는 나만 아는 사실이다.

아무도 내 글 안봐서 나만 아는 사실이다.

세상 사람들에겐 비밀이다.

 

매크로를 활용한 함수 미작동

이게 무슨 소리일까 궁금하지 않은가?

궁금하지 않다고? 상관없다. 본인은 궁금하기 때문에 알아볼 것이다.

#define printf              // printf를 빈 매크로로 정의

printf("Hello, world!");    // 아무것도 출력되지 않음

이렇게 printf 함수를 먹통으로 만들어 보았다. 정말 신기하지 않은가?

정말 신기하게도, 진짜 신기하지 않다. 정말이다.

오늘도 지식이 늘었다.

 

마치며

위 코드들이 좀 아닌 것 같다고 생각하는가?

이 글은 매크로를 이해하는 데에 중점을 둔다. 그러므로 너무 세상만사 꼬여있지 않길 바란다.

정 내 코드를 보고 울화가 치밀어 밤새 잠을 못 이루고 눈물이 벌벌 떨리며 손발이 난다면 직접 비밀글로 댓글을 적길 바란다.

그럼 성심 성의껏 슬퍼하겠다.


참고 및 출처

  • 코딩 도장