C 언어제서는 컴파일러에 특정 작업을 지시하는 전처리기(preprocessor)를 제공합니다. 보통 전처리기는 반복되는 값이나 작업을 미리 정의할 때 사용하며, 컴파일 옵션 설정이나 조건부 컴파일도 가능합니다.
배열이나 동적 메모리를 할당한 포인터는 반복문과 함께 사용하는 경우가 많습니다. 보통 배열, 메모리 크기만큼 반복하면서 값을 출력하거나 저장하죠.
#inlcude <stdio.h>
void 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]);
}
}
실행 결과
a b c d e f g h i j
이 코드의 문제점은 10이 3번 반복된다는 점입니다. 만약 배열의 크기를 바꾸면 반복문에 있는 10도 전부 바꿔야 합니다. 여기서는 10이 3개뿐이라 바꾸는데 큰 문제가 없지만, 사용하는 부분이 많아지면 숫자를 바꾸기도 점점 힘들어지고 실수할 가능성도 높아집니다.
특히, 10은 배열 s1의 크기를 뜻하지만, 코드에 내용이 더 추가돼서 배열의 크기와는 별개로 10을 사용할 수도 있습니다. 즉, 의미가 서로 다른 10이 섞여서 사용되면 각각의 의미가 헷갈리기 쉽습니다.
이런 문제를 해결할 때는 매크로를 정의하면 됩니다. #define 지시자는 값을 다른 이름으로 정의하며 이름을 짓는 방법은 변수와 같습니다. 보통 매크로는 대문자를 사용합니다.
#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
이처럼 연관되는 값이 계속 사용될 때는 값을 일일이 입력하기 보다는 매크로를 정의하여 사용하는 것이 좋습니다. 만약 배열 s1 크기를 변경하고 싶다면 #define 부분의 10을 수정하면 ARRAY_SIZE 매크로가 사용된 부분에 일괄 적용됩니다. 즉, 코드가 길어지고 복잡해졌을 때 코드 입력 실수를 줄일 수 있습니다.