#define에 전달인자를 사용함으로써, 함수처럼 보이고 함수처럼 행동하는, 함수 같은 매크로(function-like macro)를 만들 수 있다. 함수 같은 매크로 정의는 하나 또는 그 이상의 전달인자를 괄호 안에 넣는다.
ex)
#define A(X,Y) (((X)+(Y)))
위 정의는 프로그램에서 다음과 같이 사용된다.
int z = A(3,4);
z == 7
ex)
#define SQUARE(X) X*X
int main
{
int x = 5;
printf("%d", SQUARE(x+2));
}
위 출력은 49로 예상하지만 실제 출력은 17이다. 예상과 다른 결과가 나오는 이유는, 전처리기는 계산을 하지 않고, 단순히 문자열만 대체하기 때문이다. 위 매크로에서 X를 X+2로 대체한다. 그래서 X*X 는 X+2 * X+2가 된다. 그러므로 5+2*5+2 가 되어 출력은 17이 된다.
위 예제는 함수호출과 매크로 호출의 차이를 보여준다. 함수 호출은 전달인자의 값을 프로그램이 실행중일 때 함수에 전달한다. 매크로 호출은 전달인자 토큰을 컴파일 이전에 프로그램에 전달한다. SQUARE(x+2)의 결과가 49가 되게 ㅎ려면 괄호를 사용해야 한다. #define SQUARE(X) (X)*(X)
일반적으로, 증가 연산자와 감소연산자를 매크로와 함께 사용하지 않아야한다.
매크로 전달인자로 문자열 만들기 : #연산자.
#define PSQR(X) printf("x의 제곱은 %d이다.\n",((X)*(X)))
위와 같은 매크로가 있을 때 PSQR(8)의 출력은
x의 제곱은 64이다.
와 같다.
큰 따옴표 안에 있는 X는 대체되는 토큰이 아니라 일반적인 텍스트이다. 함수 같은 매크로의 몸체(대체 리스트)에 있는 #기호는, 토큰을 문자열로 변환하는 전처리기 연산자이다.
ex)
#define PSQR(X) printf(""#X"의 제곱은 %d이다.\n",((X)*(X));
라고 가정하고 int y = 5; 일때
PSQR(y)는
y의 제곱은 25이다.
라고 출력된다.
PSQR(2+4)
2+4의 제곱은 3이다
라고 출력된다.
가변전달인자 매크로 : ...과 __VA_ARGS__
매크로 정의 전달인자 리스트의 마지막 전달인자로 생략기호(마침표 3개)를 사용할 수 있다는 것이다. 생략기호를 사용한다면, 미리 정의된 매크로 __VA_ARGS__를 사용할 수 있다.
ex)
#define PR(...) printf(__VA_ARGS__)
PR("잘 있었나!");
PR("무게 = %d,배송료 = $%.2f\n",wt,sp);
결과적으로 다음과 같다.
printf("잘 있었나!");
printf("무게 = %d,배송료 = $%.2f\n",wt,sp);
생략기호는 반드시 마지막 매크로 전달인자에 대해서만 사용해야 한다.
매크로는, 조심해서 사용하지 않으면 엉뚱한 부작용을 일으킬 수 있어 함수를 사용하는 것보다 까다롭다.
매크로와 함수중 선택하는 것은, 시간 절약이냐 메모리 절약이냐 놓고 선택하는것과 같다. 매크로를 20번 사용하는 것은, 프로그램에 코드 20라인을 넣는것과 같다. 함수는 20번 사용하더라도 함수 문장들이 프로그램에 단 한번 사용한다. 매크로에 비해 함수가 메모리 공간을 적게 차지한다. 그러나 함수가 있는 곳으로 프로그램 제어가 매번 이동했다가 다시 호출 프로그램으로 돌아와야 함으로 시간은 더걸린다.
매크로는 변수의 데이터형에 신경쓸 필요가 없다는 것이 장점이다. 매크로는 int형 float형에 모두 사용할 수 있다.
일반적으로 프로그래머들은, 다음과 같은 간단한 함수들을 위해 매크로를 사용한다.
#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
#define ABS(X) ((X)< 0 ? -(X) : (X))
#define ISSIGN(X) ((X)=='+' || (X) == '-' ? 1 : 0)
매크로 사용 팁
매크로 이름에는 스페이스가 없지만 대체 문자열에는 스페이스가 나타날 수 있다.
개별 전달인자의 앞뒤에 그리고 정의 전체를 괄호로 둘러 싸라.
매크로 함수의 이름에는 대문자를 사용하라.
'Programming > C' 카테고리의 다른 글
전처리기 지시자와 매크로 (0) | 2019.07.17 |
---|---|
파일 포함 시키기 : #include (0) | 2019.07.17 |
C 전처리기와 C 라이브러리 (0) | 2019.07.10 |
C 비트 연산 - 정리 (0) | 2019.07.10 |
C 비트 필드 (0) | 2019.07.10 |