매크로 함수와 미리 정의된 매크로
✒️ 2025-05-15 15:52 내용 수정
수제비 2024 정보처리기사 필기 5판 1권의 내용을 정리
TCPSchool의 내용을 참고하여 정리
매크로 함수
함수처럼 동작하는 매크로
#define선행처리 지시문에서 인수로 함수의 정의를 전달하여 함수처럼 동작하는 매크로를 매크로 함수라고 한다.
#include <stdio.h>
#define ADD(A, B) A+B
int main(void)
{
int result;
int num1 = 10, num2 = 5;
printf("%d와 %d의 합 : %d\n", num1, num2, ADD(num1, num2));
return 0;
}
10와 5의 합 : 15
- 매크로 함수는 단순 치환만 해주기 때문에 일반 함수와 완전히 같은 방식으로 동작하진 않는다.
- 일반 함수는 인수를 프로그램 실행 중에 전달 받지만, 매크로 함수는 인수를 컴파일 이전에 미리 치환하기 때문에 인수를 전달할 때 주의해야 한다.
- 매크로 함수를
()로 감싼다. - 매크로 함수의 인수를 각각
()로 감싼다. - 매크로 함수 호출 시 증감 연산자(
++,--)나 복합 대입 연산자 사용을 자제한다.
- 매크로 함수를
- 일반 함수는 인수를 프로그램 실행 중에 전달 받지만, 매크로 함수는 인수를 컴파일 이전에 미리 치환하기 때문에 인수를 전달할 때 주의해야 한다.
#include <stdio.h>
#define ADD(A, B) A+B
#define MULT(X) X*X
int main(void)
{
int result;
int num1 = 10, num2 = 5;
//printf("%d와 %d의 합 : %d\n", num1, num2, ADD(num1, num2));
printf("%d의 제곱 : %d\n", num1, MULT(num1));
printf("%d의 제곱 : %d\n", num1+1, MULT(num1+1)); // 일반 함수와는 다르게 동작
return 0;
}
- 두 번째 경우는
(10 + 1) * (10 + 1) = 121연산된 것이 아닌10 + 1 * 10 + 1 = 21로 연산된 것이다.- 따라서
#define내의 인자를()로 묶어야 이런 문제를 방지할 수 있다.
- 따라서
10의 제곱 : 100
11의 제곱 : 21
#include <stdio.h>
#define ADD(A, B) A+B
#define MULT(X) (X)*(X) // ()로 인자를 묶기
int main(void)
{
int result;
int num1 = 10, num2 = 5;
//printf("%d와 %d의 합 : %d\n", num1, num2, ADD(num1, num2));
printf("%d의 제곱 : %d\n", num1, MULT(num1));
printf("%d의 제곱 : %d\n", num1+1, MULT(num1+1));
return 0;
}
10의 제곱 : 100
11의 제곱 : 121
- 매크로 함수를 사용하면 단순 치환만 해주기 때문에 인수 타입을 신경 쓸 필요가 없고, 여러 개의 명령문을 동시에 포함할 수 있다.
- 또한 함수 호출에 의한 성능 저하가 일어나지 않아 프로그램의 실행 속도가 향상된다.
- 하지만 일반 함수와 완벽히 같은 방법으로 동작하는 것이 아니기에 원하는 결과를 얻는 정확한 매크로 함수 구현과 디버깅에 문제가 생길 수 있다.
- 따라서 매크로 함수는 크기가 큰 함수보단 간단한 함수를 대체하여 사용하는 것이 좋다.
#, ## 연산자
#연산자 : 매크로 함수의 대체 리스트(replacement-list) 안의 인수 앞에 사용하여 토큰을 문자열로 변환 시켜준다."#인수"형태로 사용한다.- 예제를 보면 해당 토큰을 실인수로 치환하여 그대로 문자열 상수에 변환된다.
#include <stdio.h>
#define SQR(X) printf("("#X")의 제곱 : %d\n", ((X)*(X)))
int main(void)
{
int x = 8;
SQR(x);
SQR(10 + 5);
return 0;
}
(x)의 제곱 : 64
(10 + 5)의 제곱 : 225
##연산자 : 두 개의 토큰을 하나의 토큰으로 결합해준다.- 객체 같은 매크로의 대체 리스트에도 사용할 수 있다.
- 연산자 사용 시 변수나 함수 이름을 프로그램의 런타임에 정의(동적)할 수 있다.
XN(n) x ## n에서##연산자로x와n토큰을 결합한xn을 만든다.XN(1)이라면x1이라는 토큰이 생성된다.int XN(1) = 10은int x1 = 10으로 동작한다.
#include <stdio.h>
#define XN(n) x ## n
int main(void)
{
int XN(1) = 10;
printf("x1에 저장된 값 : %d\n", x1);
return 0;
}
x1에 저장된 값 : 10
미리 정의된 매크로
- C에서 컴파일러가 참고해야 할 정보를 알려주기 위해 미리 정의된 매크로가 있으며,
#define선행처리 지시자로 정의하지 않아도 사용할 수 있다.- 사용자가 이 매크로를 재정의할 수 없다.
| 매크로 | 설명 |
|---|---|
__DATE__ |
선행처리가 "Mmm dd yyyy" 형식으로 날짜를 문자열로 나타냄 |
__TIME__ |
선행처리가 "hh:mm:ss" 형식으로 시간을 문자열로 나타냄 |
__FILE__ |
현재 소스 파일의 이름을 나타내는 문자열 |
__LINE__ |
현재 소스 파일에서 처리 중인 라인 번호를 나타내는 문자열 |
__STDC__ |
컴파일러가 C 표준을 따르면 1로 설정 |
__STDC_HOSTED__ |
호스트 환경이 아니면 0, 호스트 환경이면 1로 설정 |
#include <stdio.h>
int main(void)
{
printf("선행처리 수행된 날짜 %s\n", __DATE__);
printf("선행처리 수행된 시간 %s\n", __TIME__);
printf("소스 파일 이름 : %s\n", __FILE__);
printf("현재 소스 파일에서 처리 중인 라인 번호 : %d\n", __LINE__);
printf("__STDC__ : %d\n", __STDC__);
printf("__STDC_HOSTED__ : %d\n", __STDC_HOSTED__);
return 0;
}
선행처리 수행된 날짜 Apr
선행처리 수행된 시간 12:54:45
소스 파일 이름 : C:\Users\user\Desktop\CPractice\defineTest\predefinedMacro.c
현재 소스 파일에서 처리 중인 라인 번호 : 8
__STDC__ : 1
__STDC_HOSTED__ : 1