-
Macro가 뭘까?Programming🧑💻/Cpp 2025. 2. 12. 15:36
매크로는 전처리기에게 "이 텍스트를 저 텍스트로 바꿔주세요"라고 지시하는 일종의 치환 규칙입니다.
메크로 기본 개념
가장 단순한 형태의 메크로는 #define을 사용한 상수 정의입니다.
#define PI 3.14159 #define MAX_STUDENTS 30 int main() { double circle_area = PI * radius * radius; // 컴파일 전에 PI가 3.14159로 치환됨 int students[MAX_STUDENTS]; // MAX_STUDENTS는 30으로 치환됨 }
여기서 중요한 것은 메크로가 동작하는 시점입니다. 컴파일러가 코드를 컴파일하기 전에, 전처리기가 먼저 모든 메크로를 치환합니다.
위 코드는 전처리 후에 다음과 같이 변합니다.
int main() { double circle_area = 3.14159 * radius * radius; int students[30]; }
메크로는 함수처럼 인자를 받을 수도 있습니다.
#define SQUARE(x) ((x) * (x)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) int main() { int result = SQUARE(5); // 25가 됨 int bigger = MAX(10, 20); // 20이 됨 }
메크로의 장단점
장점
1. 컴파일 시간 최적화 : 메크로는 컴파일 전에 처리되므로, 함수 호출 오버헤드가 없습니다.
일반적인 함수 호출 과정은 다음과 같습니다.
int add(int a, int b) { return a + b; } int main() { int result = add(5, 3); }
이 코드가 실행될 때 다음과 같은 과정이 일어납니다
- 현재 실행 지점의 주소를 스택에 저장
- 함수 인자들을 스택에 푸시
- 프로그램 카운터를 함수의 시작 주소로 변경
- 함수 코드 실행
- 반환값을 레지스터나 스택에 저장
- 원래 실행 지점으로 돌아감
이 모든 과정을 "함수 호출 오버헤드"라고 합니다.
위와 같은 함수를 메크로를 이용해 구현하면 다음과 같습니다.
#define ADD(a,b) ((a) + (b)) int main() { int result = ADD(5, 3); }
해당 코드가 전처리과정을 거치면 다음과 같이 바뀝니다.
#define ADD(a,b) ((a) + (b)) int main() { int result = ADD(5, 3); }
여기서는
- 함수 호출이 없음
- 스택 조작이 없음
- 프로그램 카운터 변경이 없음
- 단순히 더하기 연산만 수행
이렇게 메크로를 사용하면 컴파일 이전의 전처리단계에서 해당 부분이 자동으로 치환되기 때문에 컴파일 이후 프로그램 실행시 함수를 호출하면서 생기는 오버헤드를 제거할 수 있습니다.
2. 타입 독립성 : 메크로는 타입에 구애받지 않고 사용할 수 있습니다.
#define MAX(a,b) ((a) > (b) ? (a) : (b)) int i_max = MAX(10, 20); // int형에서 동작 double d_max = MAX(3.14, 2.72); // double형에서도 동작
메크로의 경우 단순히 텍스트를 치환하는 것으로 취급되기 때문에 타입에 영향을 받지 않습니다.
단점
- 디버깅의 어려움: 전처리된 코드를 디버깅하기가 어렵습니다.
- 타입 체크 불가: 컴파일러의 타입 체크를 받지 않아 예상치 못한 오류가 발생할 수 있습니다.
- 복잡한 로직 구현의 어려움: 복잡한 로직을 매크로로 구현하면 코드가 매우 읽기 어려워집니다.
현대적인 대안
위와 같은 단점 때문에 cpp에서는 다음과 같은 현대적인 방법들을 추천합니다.
1. 상수 메크로 대신 const 사용
// 매크로 대신 const double PI = 3.14159; const int MAX_STUDENTS = 30;
2. 함수형 매크로 대신 인라인 함수 사용
- 컴파일러에게 "가능하다면 함수 호출 대신 코드를 직접 삽입해달라"고 요청
- 매크로와 비슷한 성능 최적화 가능
- 하지만 타입 안정성과 디버깅의 용이성은 유지
// 매크로 대신 template<typename T> inline T square(T x) { return x * x; } template<typename T> inline T max(T a, T b) { return a > b ? a : b; }
'Programming🧑💻 > Cpp' 카테고리의 다른 글
서브 루틴과 코루틴 (0) 2025.02.13 빌드 과정과 #include의 역할 이해하기 (0) 2025.02.12 헤더파일은 뭐고 왜 필요한가? (0) 2025.02.12 L-value와 R-value (0) 2025.02.06 함수 호출시 매개변수 전달 방법 3가지 (0) 2025.02.05