75 매크로 사용하기
C 언어에서는 컴파일러에 특정 작업을 지시하는 전처리기(preprocessor)를 제공합니다. 보통 전처리기는 반복되는 값이나 작업을 미리 정의할 때 사용하며 컴파일 옵션 설정이나 조건부 컴파일도 가능합니다.
이번에는 전처리기에서 #define으로 매크로를 정의하는 방법을 알아보겠습니다.
75.1 매크로 정의하기
배열이나 동적 메모리를 할당한 포인터는 반복문과 함께 사용하는 경우가 많습니다. 보통 배열, 메모리 크기만큼 반복하면서 값을 출력하거나 저장하죠.
간단하게 배열을 선언한 뒤 반복문으로 문자를 하나씩 저장하고 출력해 보겠습니다.
array.c
#include <stdio.h> int main() { char s1[10]; // 문자 10개 크기의 배열 선언 for (int i = 0; i < 10; i++) // 배열 크기만큼 반복 { s1[i] = 97 + i; } for (int i = 0; i < 10; i++) // 배열 크기만큼 반복 { printf("%c ", s1[i]); } return 0; }
실행 결과
a b c d e f g h i j
이 코드의 문제점은 10이 3번 반복된다는 점입니다. 만약 배열의 크기를 바꾸면 반복문에 있는 10도 전부 바꿔야 합니다. 여기서는 10이 3개뿐이라 바꾸는데 큰 문제가 없지만, 사용하는 부분이 많아지면 숫자를 바꾸기도 점점 힘들어지고 실수할 가능성도 높아집니다.
특히, 10은 배열 s1의 크기를 뜻하지만, 코드에 내용이 더 추가돼서 배열의 크기와는 별개로 10을 사용할 수도 있습니다. 즉, 의미가 서로 다른 10이 섞여서 사용되면 각각의 의미가 헷갈리기 쉽습니다.
이런 문제를 해결할 때는 매크로를 정의하면 됩니다. #define 지시자는 값을 다른 이름으로 정의하며 이름을 짓는 방법은 변수와 같습니다. 보통 매크로는 대문자를 사용합니다.
- #define 매크로이름 값
다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요.
define_macro.c
#include <stdio.h> #define ARRAY_SIZE 10 // 10을 ARRAY_SIZE로 정의 int main() { char s1[ARRAY_SIZE]; // 10 대신 ARRAY_SIZE 매크로 사용 for (int i = 0; i < ARRAY_SIZE; i++) // 10 대신 ARRAY_SIZE 매크로 사용 { s1[i] = 97 + i; } for (int i = 0; i < ARRAY_SIZE; i++) // 10 대신 ARRAY_SIZE 매크로 사용 { printf("%c ", s1[i]); } return 0; }
실행 결과
a b c d e f g h i j
먼저 #define을 사용하여 값 10을 ARRAY_SIZE로 정의했습니다.
#define ARRAY_SIZE 10 // 10을 ARRAY_SIZE로 정의
이제 10을 써야 할 자리에 앞에서 정의한 ARRAY_SIZE 매크로를 사용했습니다. 배열을 선언할 때도 ARRAY_SIZE를 사용하고 반복문에서도 ARRAY_SIZE를 사용하니 코드가 좀 더 명확해졌죠?
char s1[ARRAY_SIZE]; // 10 대신 ARRAY_SIZE 매크로 사용 for (int i = 0; i < ARRAY_SIZE; i++) // 10 대신 ARRAY_SIZE 매크로 사용 { s1[i] = 97 + i; } for (int i = 0; i < ARRAY_SIZE; i++) // 10 대신 ARRAY_SIZE 매크로 사용 { printf("%c ", s1[i]); }
#define은 컴파일 직전에 처리되므로 전처리기 과정을 거치면 ARRAY_SIZE는 10으로 바뀌게 됩니다(바뀐 코드는 전처리기 과정 때 임시로 생성될 뿐 원본 코드에 영향을 주지 않으니 걱정하지 않아도 됩니다).
이처럼 연관되는 값이 계속 사용될 때는 값을 일일이 입력하기 보다는 매크로를 정의하여 사용하는 것이 좋습니다. 만약 배열 s1 크기를 변경하고 싶다면 #define 부분의 10을 수정하면 ARRAY_SIZE 매크로가 사용된 부분에 일괄 적용됩니다. 즉, 코드가 길어지고 복잡해졌을 때 코드 입력 실수를 줄일 수 있습니다.
#define으로 정의한 매크로는 다른 이름으로 다시 정의할 수 있습니다.
#define ARRAY_SIZE 10 // 10을 ARRAY_SIZE로 정의 #define DEFAULT_ARRAY_SIZE ARRAY_SIZE // ARRAY_SIZE를 DEFAULT_ARRAY_SIZE로 정의
이렇게 정의하면 결과적으로 DEFAULT_ARRAY_SIZE는 10입니다.
#define으로 정의한 매크로를 해제하고 싶을 때는 #undef를 사용합니다.
- #undef 매크로이름
다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요.
undefine_macro.c
#include <stdio.h> #define COUNT 10 // 10을 COUNT로 정의 int main() { printf("%d\n", COUNT); // 10 #undef COUNT // 앞에서 정의한 COUNT 해제 #define COUNT 20 // 20을 COUNT로 정의 printf("%d\n", COUNT); // 20: #undef로 COUNT를 해제한 뒤 20을 COUNT로 정의했으므로 20이 출력됨 return 0; }
실행 결과
10 20
#define으로 정의한 매크로를 해제(삭제)하고 싶다면 #undef에 매크로 이름을 지정해주면 됩니다. 만약 #undef로 해제된 매크로를 계속 사용하면 컴파일 에러가 발생합니다.
여기서는 #undef을 사용하여 COUNT를 해제한 뒤 다시 #define을 사용하여 20을 COUNT로 정의했습니다.