[C]매크로(mecro)
이번 포스트는 매크로(mecro)에 관한 내용입니다.
1️⃣ #define & #undef
(1) #define
- 전처리과정에서
가 보이면 모두식별자 로 바꿔줍니다.대체_목록 -
대체_목록 없이
으로 쓰이면 내용으로 바꿔주지 않고 단순히 정의(define)만 됩니다.( 인클루드 가드에 사용)#define 식별자
(2) #undef
- 이미 정의된
가 있을 경우 없애 줍니다.식별자
< 정의 매크로 예시 >
..헤더 내용..
(3) 미리 정의되어 있는 #define예
- C언어에는 미리 정의되어 있는 매크로들이 있습니다.
- __FILE__: 현재 파일의 이름을 문자열로 표시합니다.
- __LINE__: 현재 코드의 줄 번호를 정수형으로 표시합니다.
< 오류 출력시 사용 >
error: test.c, line 5.
2️⃣ 조건부 컴파일
(1) 조건부 컴파일
- 대표적인 예시로
unist.h
헤더의 경우 윈도우운영체제에서는io.h
헤더로 선언되어 있습니다. - _WIN32는 32, 64비트 윈도우운영체제를 뜻합니다.
- 즉, 다음과 같이 윈도우운영체제일 경우
io.h
헤더를, 아닐 경우unistd.h
헤더를 호출합니다.
(2) 인클루드 가드로 이용
< one.h >
#include "two.h"
/* one헤더파일 코드 생략 */
< two.h >
#include "one.h"
/* two헤더파일 코드 생략 */
< test.c >
#include "one.h"
int main(void)
{
printf("Hello world!\n");
return (0);
}
위의 세파일을 만들고 test.c
파일을 전처리 단계만을 거치면 다음과 같이 무한으로 헤더가 확장됩니다.
< 전처리 단계를 거친후 test.c >
...
...
/* one헤더파일 코드 생략 */
/* two헤더파일 코드 생략 */
/* one헤더파일 코드 생략 */
...
...
/* two헤더파일 코드 생략 */
/* one헤더파일 코드 생략 */
/* two헤더파일 코드 생략 */
/* one헤더파일 코드 생략 */
int main(void)
{
printf("Hello world!\n");
return (0);
}
one.h가 two.h를 복붙
->two.h가 one.h을 복붙
…을 끝도 없이 반복하게 됩니다.(컴파일러가 강제로 멈춤)- 보통 이것을 순환 헤더 인클루드(circular header include)라고 합니다.(“헤더가 꼬였다”)
- 그렇기 때문에
#include
는 되도록이면 .c에서만 하는 것이 좋습니다. 하지만 어쩔 수없이 헤더 파일을 서로 인클루드해야 할 일이 있습니다. - 이러한 순환 헤더 인클루드는
#ifndef
를 사용하여 방지할 수 있습니다.
(2) 이중헤더방지 매크로(인클루드 가드) 구현 예
3️⃣ 기타 이용
(1) 주석으로 이용
- 매크로를 이용하여 주석처리를 할 수 있습니다.
- /* */를 이용하여 주석을 처리할 수 있지만 주석을 지우고 쓰고를 반복할 때 시작과 끝을 까먹을 때가 있습니다.
- 또한 /* */를 이용한 주석처리는 중첩이 안됩니다.
< 매크로 주석 사용 >
< 매크로 주석 해제 >
(2) #error(에러출력 매크로)
- 컴파일 도중에 강제로 오류를 발생시키는 매크로입니다.
버전이 다르면
,정의가 안되어 있으면
,아직구현안한 운영체제환경이면
등등 컴파일을 못하게 하고 에러를 출력합니다.- 메세지를 꼭 큰따옴표로 감쌀 필요는 없습니다.
< 버전관리 사용예 >
test.c:6:2:
#
< 운영체제 사용예 >
test.c:6:2:
#
4️⃣ 컴파일 중에 매크로 정의하기('-D' 옵션)
(1) A값 정의
< base.c 파일 >
#include <stdio.h>
int main(void)
{
printf("%d", A); // A가 선언되어 있지않음
}
< -D옵션 사용1 >
$> ./a.out
- 단순히
-DA
로 작성하면#define A (1)
과 같이 적용됩니다. (#define A
가 아님)
< -D옵션 사용2(숫자지정) >
$> ./a.out
#define A (42)
와 같은 결과가 출력됩니다.
(2) 배포용으로 컴파일하기 ('-D' + 'NDEBUG')
- 배포(release)모드 실행파일을 컴파일해달라는 매크로 입니다.
- NDEBUG는 ‘디버그가 아니다’라는 뜻입니다.
assert()
가 사라집니다.- 디버그 모드에서만 실행될 코드는
#if !defined(NDEBUG)
속에 넣습니다.
- 추가적으로 다음과 같은 매크로를 직접 정의(자기만의 매크로명)해 사용하는 프로젝트들도 많습니다.
- DEBUG: 디버그용 빌드
- RELEASE: 배포용 빌드
- 등등.. 이런식으로 자기만의 매크로명으로 다양한 빌드를 지정할 수 있습니다.