매크로
-> 단순 치환
-> #define으로 정의한다.
# : 전처리 지시자
-> 컴파일 이전에 수행
define : 정의하다.
-> 컴파일 이전에 정의하라고 명령.
#1 매크로 상수
#define 매크로이름 치환할 값
매크로 상수 사용 시 주의사항
-> 단순 치환이기 때문에 세미콜론을 작성할 경우 세미콜론까지 치환해버린다.
예)
#define PI 3.14f;
// 입력
cout << PI << endl;
// 출력
cout << 3.14f; << endl;
매크로 이름 뒤에 치환할 값이 없다면 공백으로 처리한다.
예)
#define PI
// 입력
cout << PI << endl;
// 출력
cout << << endl;
#define 매크로는 주로 배열의 크기를 다룰 때 사용을 한다.
#define MAX_SIZE 512
void main()
{
int iArr[MAX_SIZE] = {};
}
#2 매크로 함수
-> 매크로를 함수처럼 사용하는 것
#define 매크로이름() 정의부 구현
#define SQUARE(n) n * n
이것은 다음 함수와 같다.
int Square(int _n)
{
return _n *_n;
}
일반 함수 호출
-> 함수가 위치한 호출 번지로 이동 -> Stack 영역 할당 및 매개 변수 복사
-> 연산 -> 값 반환 및 Stack 영역 정리 -> 호출했던 위치로 복귀
매크로 함수 호출
-> Stack 영역이 할당 및 복사가 없다.
-> 속도가 빠르다.
-> 함수 호출을 위한 연산들이 필요 없어진다.
매크로 함수의 주의점
#1 연산을 수행할 때 연산자 우선순위를 명확하게 표시해야한다.
예)
#define SQUARE(n) n * n
cout << SQUARE(2 + 2) << endl; // cout << 2 + 2 * 2 + 2 << endl;
이렇게 되면 연산자 우선순위가 곱셈을 먼저 수행해서 2 * 2 + 2 + 2 = 8이 된다.
하지만 다음과 같이 #define 함수를 정의할 때 우선순위를 정해주면 원하는 값이 나오게 된다.
#define SQUARE(n) (n) * (n)
cout << SQUARE(2 + 2) << endl; // cout << (2 + 2) * (2 + 2) << endl;
#2 함수의 정의부가 길 경우
-> 매크로 함수는 줄 바꿈을 할 수 없다.
-> 무조건 1줄로만 매크로로 인식한다.
-> 이를 해결하기 위해 줄바꿈 전에 \(역슬러쉬)로 다음 줄에도 매크로 이어진다. 라고 알려주어야 한다.
#define SQUARE(n) \
n * n
-> 단, \ 뒤에 공백 문자가 올 경우 컴파일 오류가 발생한다!
#define SQUARE(n) \공백
n * n
#3 디버깅이 불가능하다
-> 매크로 함수는 짧지만 자주 사용하는 함수를 매크로 함수로 정의하는 것이 좋다.
예를 들어 포인터 할당을 해제하는 경우가 생겼을 때
if(p != nullptr)
{
delete p;
p = nullptr;
}
다음과 같이 매크로를 지정하여 손쉽게 할당 해제가 가능하다.
#define SAFE_DELETE(p) if(p) { delete p; p = nullptr; }
함수()
{
코드 블럭
SAFE_DELETE(포인터 값);
}
#define 으로 정의된 상수는 항상 괄호로 감싸준다.
#define NUM (1)
상수는 #define 보다 const 상수 변수로 선언한다.
'프로그래밍 언어 > C++' 카테고리의 다른 글
[C++] 함수를 객체로 사용하기 (std::function, std::mem_fn, std::bind) (0) | 2023.09.23 |
---|---|
[C] 함수 포인터 사용법 & 예제 총 정리 (0) | 2023.09.23 |
[실4] 28279 - 덱2 (0) | 2023.09.19 |
[C++] emplace_back 과 push_back 의 차이 (0) | 2023.09.19 |
[C] 배열과 포인터의 관계 (변수형 포인터, 상수형 포인터), 포인터로 배열 변경하기 (0) | 2023.09.17 |