C언어에서는 #define 선행처리 지시문에 인수로 함수의 정의를 전달함으로써, 함수처럼 동작하는 매크로를 만들 수 있다.
이러한 매크로를 매크로 함수라고 하며 컴파일 전에 실행된다.
파라미터가 없는 매크로는 단순 매크로(simple macro), 혹은 C 표준에 의거한 이름인 유사개체 매크로(object-like macro)라고 부른다.
C에서 매크로를 상수처럼 사용할 땐 이름을 전무 대문자로 작성하는 것이 관습이지만 이외의 용도에서는 통일된 의견은 없다.
매크로를 이용해 상수를 지정했을 때의 장점:
1. 가독성 향상: 적절한 이름을 지으면 독자가 상수의 의미를 쉽게 이해할 수 있다.
2. 프로그램의 수정성 향상: 프로그램 전체에서 사용하는 상수의 값을 단순히 매크로 정의 하나 수정함으로써 바꿔줄 수 있다.
3. 일관성 없는 코드나 오타 방지: 프로그램 내에서 3.14159같은 상수가 여러번 등장한다면 실수로 3.1416이라든가 3.14195로 잘못 적을 수도 있다.
단순 매크로 서식:
#define 식별자 대체목록
매크로 작성시 주의할 점은 위에 적힌 것 말고 다른 것을 적으면 안된다. 예를 들어 등호를 적는다든가 ;를 붙히면 대체목록의 일부가 되어버린다.
#define N = 100 /*** 실수 ***/
#define N 100; /*** 실수 ***/
각각 "100"이 아니라 "= 100"과 "100;"이 되어버린다.
대체목록(replacement-list):
전처리 토큰들의 임의의 연속체
식별자, 키워드, 숫자 상수, 문자 상수, 문자열 리터럴, 연산자, 구두점 등을 의미
매크로 정의를 만나게 되면 전처리기는 식별자가 대체목록을 의미하게 됨을 표시
파일에 식별자가 등장하게 되면 전처리기는 그걸 대체목록으로 대체해준다
형 이름 개명:
다음 예시는 BOOL이라는 식별자를 int로 대체하겠다는 의미이다. C에서는 boolean type이 없기 때문에 기능적으로 boolean type이더라도 표기는 int로 해야한다. 하지만 매크로를 통해 BOOL로 표시하여 가독성을 높일 수 있다.
#define BOOL int
조건적 컴파일 제어:
다음 예시는 디버깅 관련 출력을 담당하는 코드도 추가적으로 컴파일할 수 있게 "디버깅 모드"로 프로그램을 컴파일할 수 있게 해주는 역할을 하게 만들 수 있다
#define DEBUG
매개변수 매크로 서식
#define 식별자( x1 , x2 , … , xn )대체목록
이때 매크로 이름과 괄호사이에는 공백이 있으면 안된다. 그럴 경우 전처리기는 단순 매크로로 인식하여 매크로 이름 뒤의 것들을 모두 대체목록으로 인식할 것이다.
매크로 함수:
#define SQR(X) X*X
주의: 매크로는 해당 문자를 대체목록으로 대체한다. 따라서 다음과 같은 사용은 주의해야한다.
ex)int x = 5; SQR(x+3); 결과: 23X를 x+3로 대체하는 것이므로 x+3x+3이 된다. 따라서 5+35+3 = 5+15+3 = 23가 된다.
매크로 정의는 #과 ## 두가지를 가진다. 둘 다 컴파일러는 인식할 수 없고 전처리 때 처리된다.
# 연산자:
매크로 입력변수를 문자열 리터럴로 치환
매개변수 매크로의 대체 목록에서만 등장
#define PRINT_INT(n) printf(#n " = %d\n", n)
PRINT_INT(i / j);
위의 발동은 다음과 같이 된다:
printf("i / j" " = %d\n", i / j);
## 연산자:
## 연산자는 두 토큰을 하나의 토큰으로 붙여준다.
#define ID(n) i##n
int ID(123);
이는 int i123;과 같이 바뀐다.