C 전처리기


C 전처리기 는 컴파일러의 일부가 아니지만 컴파일 프로세스에서 별도의 단계입니다. 간단히 말해서, C 전처리기는 실제 컴파일 전에 필요한 전처리를 완료하도록 컴파일러에 지시하는 텍스트 교체 도구에 지나지 않습니다. C Preprocessor를 CPP로 줄여서 설명하겠습니다.

모든 전처리기 명령은 파운드 기호(#)로 시작합니다. null이 아닌 첫 번째 문자여야 하며 가독성을 높이기 위해 전처리기 지시문은 첫 번째 열에서 시작해야 합니다. 모든 중요한 전처리기 지시어는 다음과 같습니다.

지시어 설명
#define 매크로 정의
#include소스 코드 파일 포함
#undef 취소 정의된 매크로
#ifdef매크로가 이미 정의된 경우 true를 반환합니다.
#ifndef매크로가 정의되지 않은 경우 true를 반환합니다.
#ifif 주어진 조건이 true인 경우 , 다음 코드를 컴파일하세요
#else#if 대안
#elif이전 #if 주어진 조건이 true가 아니고 현재 조건이 true인 경우 다음 코드를 컴파일하세요
#endif#if...#else 조건부 컴파일 블록 종료
#error표준 오류가 발생하면 오류 메시지 출력
#pragma정규화 방법을 사용하여 컴파일러 컴파일러에 특수 명령을 실행합니다

전처리기 예제

다음 예제를 분석하여 다양한 지침을 이해하세요.

#define MAX_ARRAY_LENGTH 20

이 명령은 CPP에 모든 MAX_ARRAY_LENGTH를 20으로 바꾸도록 지시합니다. 가독성을 높이기 위해 #define을 사용하여 상수를 정의하세요.

#include <stdio.h>#include "myheader.h"

이 지침은 CPP에게 시스템 라이브러리에서 stdio.h를 가져와 현재 소스 파일에 텍스트를 추가하도록 지시합니다. 다음 줄은 CPP에게 로컬 디렉터리에서 myheader.h를 가져와 현재 소스 파일에 내용을 추가하도록 지시합니다.

#undef  FILE_SIZE#define FILE_SIZE 42

이 명령은 정의된 FILE_SIZE를 취소하고 42로 정의하도록 CPP에 지시합니다.

#ifndef MESSAGE   #define MESSAGE "You wish!"#endif

이 지시문은 MESSAGE가 정의되지 않은 경우에만 MESSAGE를 정의하도록 CPP에 지시합니다.

#ifdef DEBUG   /* Your debugging statements here */#endif

이 지시문은 DEBUG가 정의된 경우 처리 문을 실행하도록 CPP에 지시합니다. 이 지시문은 컴파일 타임에 -DDEBUG 스위치를 gcc 컴파일러에 전달하는 경우 유용합니다. 이는 DEBUG를 정의하며 컴파일 중에 언제든지 디버깅을 켜거나 끌 수 있습니다.

사전 정의된 매크로

ANSI C는 많은 매크로를 정의합니다. 프로그래밍에 이러한 매크로를 사용할 수 있지만 미리 정의된 매크로를 직접 수정할 수는 없습니다.

MacroDescription
__DATE__현재 날짜, "MMM DD YYYY" 형식으로 표현되는 문자 상수입니다.
__TIME__현재 시간, "HH:MM:SS" 형식으로 표현되는 문자 상수입니다.
__FILE__ 여기에는 현재 파일 이름, 문자열 상수가 포함됩니다.
__LINE__ 여기에는 현재 줄 번호, 즉 십진수 상수가 포함됩니다.
__STDC__ 컴파일러가 ANSI 표준으로 컴파일하는 경우 1로 정의됩니다.

다음 예를 시도해 보겠습니다.

#include <stdio.h>main(){
   printf("File :%s\n", __FILE__ );
   printf("Date :%s\n", __DATE__ );
   printf("Time :%s\n", __TIME__ );
   printf("Line :%d\n", __LINE__ );
   printf("ANSI :%d\n", __STDC__ );}

위 코드(test.c 파일에 있음)를 컴파일하고 실행하면 다음과 같은 결과가 생성됩니다.

File :test.cDate :Jun 2 2012Time :03:36:24Line :8ANSI :1

전처리기 연산자

C 전처리기 프로세서는 다음과 같은 연산자를 제공합니다. 매크로 생성을 도와주세요:

매크로 연속 연산자 ()

매크로는 일반적으로 한 줄에 작성됩니다. 그러나 매크로가 너무 길어서 한 줄에 다 들어갈 수 없다면 매크로 연속 연산자()를 사용하세요. 예:

#define  message_for(a, b)  \
    printf(#a " and " #b ": We love you!\n")
문자열 상수화 연산자(#)

매크로 정의에서 매크로 매개변수를 문자열 상수로 변환해야 하는 경우 문자열 상수화 연산자(#)가 사용됩니다. 매크로에 사용되는 이 연산자에는 특정 인수 또는 인수 목록이 있습니다. 예:

#include <stdio.h>#define  message_for(a, b)  \
    printf(#a " and " #b ": We love you!\n")int main(void){
   message_for(Carole, Debra);   return 0;}

위 코드를 컴파일하고 실행하면 다음과 같은 결과가 생성됩니다.

Carole and Debra: We love you!
태그 붙여넣기 연산자(##)

매크로 정의 내의 태그 붙여넣기 연산자(##)는 두 매개 변수를 병합합니다. 두 개의 독립적인 태그를 매크로 정의에서 하나의 태그로 결합할 수 있습니다. 예:

#include <stdio.h>#define tokenpaster(n) printf ("token" #n " = %d", token##n)int main(void){   int token34 = 40;
   
   tokenpaster(34);   return 0;}

위 코드를 컴파일하고 실행하면 다음 결과가 생성됩니다.

token34 = 40

이 예제가 컴파일러에서 다음과 같은 실제 출력을 생성하기 때문에 이런 일이 발생합니다.

printf ("token34 = %d", token34);

이 예제에서는 토큰##n을 보여줍니다. 문자열 상수화 연산자(#)토큰 붙여넣기 연산자(##)를 사용하는 token34로 연결됩니다.

define() 연산자

전처리기 define 연산자는 식별자가 #define을 사용하여 정의되었는지 확인하기 위해 상수 표현식에 사용됩니다. 지정된 식별자가 정의된 경우 값은 true(0이 아님)입니다. 지정된 식별자가 정의되지 않은 경우 값은 false(0)입니다. 다음 예에서는 정의된() 연산자의 사용법을 보여줍니다.

#include <stdio.h>#if !defined (MESSAGE)   #define MESSAGE "You wish!"#endifint main(void){
   printf("Here is the message: %s\n", MESSAGE);  
   return 0;}

위 코드를 컴파일하고 실행하면 다음과 같은 결과가 생성됩니다.

Here is the message: You wish!

매개변수화된 매크로

CPP 강력한 기능은 매개변수화된 매크로를 사용하는 기능입니다. 기능을 시뮬레이션합니다. 예를 들어, 다음 코드는 숫자의 제곱을 계산합니다.

int square(int x) {   return x * x;}

다음과 같이 매크로를 사용하여 위 코드를 다시 작성할 수 있습니다.

#define square(x) ((x) * (x))

매개변수가 있는 매크로를 사용하기 전에 #define 지시어를 사용하여 정의해야 합니다. 매개변수 목록은 괄호로 묶여 있으며 매크로 이름 바로 뒤에 와야 합니다. 매크로 이름과 여는 괄호 사이에는 공백이 허용되지 않습니다. 예:

#include <stdio.h>#define MAX(x,y) ((x) > (y) ? (x) : (y))int main(void){
   printf("Max between 20 and 10 is %d\n", MAX(10, 20));  
   return 0;}

위 코드를 컴파일하고 실행하면 다음과 같은 결과가 생성됩니다.

Max between 20 and 10 is 20