매크로로 치환될 영역을 괄호로 둘러싸면 근처의 표현식으로 인해 우선순위가 바뀌는 일을 방지할 수 있다. PRE00-C 함수형의 매크로보다는 인라인이나 정적 함수를 사용하라와 PRE01-C 매크로에서는 매개 변수에 괄호를 사용하라를 참조하라.
아래 CUBE() 매크로 정의는 치환될 영역을 괄호로 둘러싸고 있지 않아 부적절하다.
#define CUBE(X) (X) * (X) * (X)
int i = 3;
int a = 81 / CUBE(i);
따라서 다음과 같이 호출하면,
int a = 81 / CUBE(i);
이렇게 확장되므로,
int a = 81 / i * i * i
결과는,
int a = (((81 / i) * i) * i);
/* 243 이 된다 */
처럼 의도와 다르게 된다.
치환될 영역을 괄호로 둘러싸면 CUBE()를 호출할 때 정확하게 치환된다.
#define CUBE(X) ((X) * (X) * (X))
int i = 3;
int a = 81 / CUBE(i);
하지만 이 방법은 PRE00-C 함수형의 매크로보다는 인라인이나 정적 함수를 사용하라를 위반하므로 매크로 대신 인라인 함수를 사용하는 편이 더 좋다.
이 코드에서는 EOF가 -1로 정의돼 있다. 매크로로 치환될 부분에는 - 연산자와 숫자 리터럴 1이 들어간다.
#define EOF -1
/* ... */
if (getchar() EOF) {
/* ... */
}
프로그래머가 getchar() != EOF에서 비교 연산자를 실수로 누락했다. 이렇게 되면 매크로 치환 이후 조건 표현식이 getchar()-1로 되어 단항 연산으로 처리되므로 부적절하게 평가된다. 언어 규칙상으로 맞지만 프로그래머가 의도한 것은 아니다.
EOF에 대한 -1 정의를 괄호로 둘러싸면 매크로 치환이 정확해진다.
#define EOF (-1)
이렇게 수정하면 예제의 코드는 매크로 치환 이후 getchar()(-1) 처럼되므로 언어 규칙상 맞지 않아 컴파일되지 않는다. 위에서 EOF 다음에 공백이 하나 있음을 주의하자. 공백이 없으면 함수형 매크로처럼 인식되고 매개변수로서는 부적절한 -1을 가지고 비정상적인 매크로 처리를 한다.
매크로 정의를 열거형 상수로 치환하면 된다.
enum { EOF = -1 }
/* ... */
if (getchar() != EOF) {
/* ... */
}
PRE02-EX1 : 매크로가 한 개의 식별자나 함수로 치환되는 경우에는 치환되는 영역 근처의 다른 표현식에 의해 영향받지 않으므로 치환되는 영역을 괄호로 둘러쌀 필요가 없다.
#define MY_PID getpid()
PRE01-C. 매크로에서는 매개변수에 괄호를 사용하라 (0) | 2021.06.01 |
---|---|
PRE00-C. 함수형의 매크로보다는 인라인이나 정적 함수를 사용하라. (0) | 2021.06.01 |
댓글 영역