C 매크로 기본 - sonkoni/Koni-Wiki GitHub Wiki
C언어 문법이 아니라 C컴파일러의 전처리기 명령어이다.
매크로는 C언어의 내부에서 각종 환경설정, 일반화 등 정말 엄청나게 많이 쓰인다.
- 세미콜론 붙이지 않는다.
- 주석은 보통 달지 않거나 별주석을 쓴다.
- 보통 대문자_형태 로 쓴다.
매크로의 주된 기능은 치환이다.
// 값을 매크로로 정의 // 10을 COUNT로 정의
#define 매크로이름 값 #define COUNT 10
// 여러 줄을 매크로로 정의 // printf 세 줄을 PRINT_NUM3으로 정의
#define 매크로이름 코드1 \ #define PRINT_No3 printf("No\n"); \
코드2 \ printf("NO\n"); \
코드3 printf("nO\n");
// 값을 붙이는 매크로 정의(##) // a와 b를 붙이는 CONCAT 매크로 정의
#define 매크로이름(a, b) a##b #define CONCAT(a, b) a##b
// 문자열로 만드는 매크로(#)
#define PRINT(s) printf(#s) ==>> PRINT(hello);
==>> printf("hello"); 로 대치. 즉, 변수를 따옴표로 싸준다.
// 정의한 매크로 해제 // COUNT 매크로 해제
#undef 매크로이름 #undef COUNT매크로를 함수처럼 쓸 수 있다. 간단한 경우에만 이렇게 하자. 요즘은 인라인 함수로 대체되는 분위기다.
// 함수 모양으로 매크로 정의 // 숫자를 출력하는 PRINT_NUM 매크로 정의
#define 매크로이름(x) 함수(x) #define PRINT_NUM(x) printf("%d\n", x)
#define 매크로이름(x) 코드조합 // do while (0)을 이용하여 매크로 안에서 변수 선언.
// if, else에서 컴파일 에러 방지
#define SWAP(a, b, type) do { \
type temp; \
temp = a; \
a = b; \
b = temp; \
} while (0)매크로는 치환이다. 이로 인해 C언어 우선순위로 의도하지 않은 결과가 나올 수 있다. 괄호를 팍팍 써서 사용해야 한다
#define MUL(a, b) a * b ==>> MUL(1 + 2, 3 + 4)
==>> 1 + 2 * 3 + 4 로 대치. 결과는 11
#define MUL(a, b) ((a) * (b)) ==>> MUL(1 + 2, 3 + 4)
==>> ((1 + 2) * (3 + 4)) 로 대치. 결과는 21
괄호를 써주면 영향 안 받아
#define ADD(a, b) a + b ==>> ADD(1, 2) * 3
==>> 1 + 2 * 3 으로 대치. 결과는 7
#define ADD(a, b) ((a) + (b)) ==>> ADD(1, 2) * 3
==>> ((1) + (2)) * 3 으로 대치. 결과는 9매크로 조건문이다. #ifdef, #ifndef, #if, defined, #elif, #else, enif 를 조합해서 사용한다.
// 매크로가 정의되어 있을 때 컴파일 // DEBUG 매크로가 정의되어 있을 때 컴파일
#ifdef 매크로 #ifdef DEBUG
코드 printf("Debug\n");
#endif #endif
// 매크로가 정의되어 있지 않을 때 컴파일 // DEBUG 매크로가 정의되어 있지 않을 때 컴파일
#ifndef 매크로 #ifndef DEBUG
코드 printf("Hello, world!\n");
#endif #endif
// 값 또는 식이 참일 때 컴파일 // DEBUG_LEVEL이 2 이상일 때 컴파일
#if 값 또는 식 #if DEBUG_LEVEL >= 2
코드 printf("Debug Level 2\n");
#endif #endif
// 조건이 항상 거짓이므로 컴파일 하지 않음
#if 0
printf("0\n");
#endif
// 조건이 항상 참이므로 컴파일함
#if 1
printf("1\n");
#endif
각종 논리연산자도 사용 가능하다.
// 매크로가 정의되어 있을 때 컴파일.
// !, &&, ||로 논리 연산 가능 // DEBUG 또는 TEST가 정의되어 있을 때 컴파일
#if defined 매크로 #if defined DEBUG || defined TEST
코드 printf("Debug\n");
#endif #endif
// DEBUG가 정의되어 있으면서
// VERSION_10이 정의되어 있지 않을 때 컴파일
#if defined (DEBUG) && !defined (VERSION_10)
printf("Debug\n");
#endif
// if, elif, else로 조건부 컴파일 // DEBUG_LEVEL의 값에 따라 컴파일
#if 조건식 #if DEBUG_LEVEL == 1
코드 printf("Debug Level 1\n");
#elif 조건식 #elif DEBUG_LEVEL == 2
코드 printf("Debug Level 2\n");
#else #else
코드 printf("Hello, world!\n");
#endif #endif
// if, elif, else로 조건부 컴파일 // PS2, USB 정의 여부에 따라 컴파일
#ifdef 매크로 #ifdef PS2
코드 printf("PS2\n");
#elif defined 매크로 #elif defined USB
코드 printf("USB\n");
#else #else
코드 printf("지원하지 않는 장치입니다.\n");
#endif #endif
// 파일 포함하기
#include <시스템경로파일> /* 기본 라이브러리나 컴파일 옵션에서 지정한 헤더파일 경로를 기준으로 포함 */
#include "임의경로파일" /* 현재 소스파일을 기준으로 헤더파일 포함 */
"msg.h" 현재소스와 같은 폴더에 있음
"inc/msg.h" 현재폴더 하위 inc 디렉토리에 msg.h 가 있음
"../msg.h" 현재폴더 상위 폴더에 msg.h 가 있음test.h / test.c 파일을 만든다고 할 때,
test.h 파일은 다음과 같이 구성해야 한다.
#ifndef 헤더이름 #ifndef Test_h
#define 헤더이름 #define Test_h
코드 #include <stdio.h>
typedef struct _DATA {
int a, b;
} DATA;
#endif /* 헤더이름 */ void GloHelloFunc (void);
#endif /* Test_h */