들어가며
매크로란 무엇일까.
게임을 자주 해본 사람이나 접해본 사람들은 매크로를 다음과 같이 이해하는 경우가 많다.
"매크로는 자동사냥 같은 거 말하는 거 아냐?"
그것에 관한 것은 잘 모르겠고, 나는 프로그래밍에 관해서 얘기할 예정이다.
매크로(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 함수를 먹통으로 만들어 보았다. 정말 신기하지 않은가?
정말 신기하게도, 진짜 신기하지 않다. 정말이다.
오늘도 지식이 늘었다.
마치며
위 코드들이 좀 아닌 것 같다고 생각하는가?
이 글은 매크로를 이해하는 데에 중점을 둔다. 그러므로 너무 세상만사 꼬여있지 않길 바란다.
정 내 코드를 보고 울화가 치밀어 밤새 잠을 못 이루고 눈물이 벌벌 떨리며 손발이 난다면 직접 비밀글로 댓글을 적길 바란다.
그럼 성심 성의껏 슬퍼하겠다.
참고 및 출처
-
코딩 도장