#if, #elif, #else 및 #endif 지시문(C/C++)
#elif, #else 및 #endif 지시문이 있는 #if 지시문은 소스 파일의 일부 컴파일을 제어합니다. 작성하는 식(#if 이후)에 0이 아닌 값이 있는 경우 #if 지시문 바로 뒤의 줄 그룹은 변환 단위에 유지됩니다.
문법
조건부 :
if-part elif-partsopt else-partopt endif-line
if-part :
if 줄 텍스트
if-line :
상수 식 #if
#ifdef 식별자
#ifndef 식별자
elif-parts :
줄 바꿈 텍스트
elif-parts elif-line 텍스트
elif-line :
상수 식 #elif
else-part :
else 줄 텍스트
else-line :
#else
endif-line :
#endif
설명
소스 파일의 각 #if 지시문은 닫 는 #endif 지시문과 일치해야 합니다. #if 지시문과 #endif 지시문 사이에는 여러 #elif 지시문이 나타날 수 있지만 #else 지시문은 하나만 허용됩니다. #else 지시문(있는 경우)은 #endif 전에 마지막 지시문이어야 합니다.
#if, #elif, #else 및 #endif 지시문은 다른 #if 지시문의 텍스트 부분에 중첩할 수 있습니다. 중첩된 각 #else, #elif 또는 #endif 지시문은 앞의 가장 가까운 #if 지시문에 속합니다.
#if 및 #ifdef 같은 모든 조건부 컴파일 지시문은 파일 종료 전에 닫는 #endif 지시문과 일치해야 합니다. 그렇지 않으면 오류 메시지가 생성됩니다. 조건부 컴파일 지시문이 포함 파일에 포함된 경우 동일한 조건을 만족해야 합니다. 포함 파일의 끝에 일치하지 않는 조건부 컴파일 지시문이 없어야 합니다.
매크로 바꾸기는 #elif 명령을 따르는 줄의 일부 내에서 수행되므로 상수 식에서 매크로 호출을 사용할 수 있습니다.
전처리기는 추가 처리를 위해 지정된 텍스트 항목 중 하나를 선택합니다. 텍스트에 지정된 블록은 모든 텍스트 시퀀스일 수 있습니다. 두 줄 이상을 차지할 수 있습니다. 일반적으로 텍스트 는 컴파일러 또는 전처리기에서 의미가 있는 프로그램 텍스트입니다.
전처리기는 선택한 텍스트를 처리하고 컴파일러에 전달합니다. 텍스트에 전처리기 지시문이 포함된 경우 전처리기는 이러한 지시문을 수행합니다. 전처리기에서 선택한 텍스트 블록만 컴파일됩니다.
전처리기는 true(0이 아닌) 상수 식을 찾을 때까지 각 #if 또는 #elif 지시문 다음에 있는 상수 식을 평가하여 단일 텍스트 항목을 선택합니다. 연결된 #elif, #else 또는 #endif 모든 텍스트(다른 #전처리기 지시문 포함)를 선택합니다.
상수 식이 모두 false이거나 #elif 지시문이 나타나지 않으면 전처리기가 #else 절 뒤에 있는 텍스트 블록을 선택합니다. #else 절이 없고 #if 블록에 있는 상수 식의 모든 인스턴스가 false이면 텍스트 블록이 선택되지 않습니다.
constant-expression은 다음과 같은 추가 제한이 있는 정수 상수 식입니다.
식에는 정수 형식이 있어야 하며 정수 상수, 문자 상수 및 정의된 연산자만 포함할 수 있습니다.
식은 사용할 수 없거나 형식 캐스트 연산자를 사용할
sizeof
수 없습니다.대상 환경이 모든 정수 범위를 나타낼 수 없습니다.
변환은 형식과 같은 방식으로 형식
int
long
을 나타내며unsigned int
unsigned long
.변환기는 문자 상수를 대상 개발 환경에 대한 집합과 다른 코드 값의 집합으로 변환할 수 있습니다. 대상 환경의 속성을 확인하려면 해당 환경에 대해 빌드된 앱을 사용하여 LIMITS의 값을 확인합니다. H 매크로.
식은 환경을 쿼리해서는 안 되며 대상 컴퓨터의 구현 세부 정보로부터 격리된 상태로 유지되어야 합니다.
전처리기 연산자
정의
정의된 전처리기 연산자는 다음 구문과 같이 특수 상수 식에서 사용할 수 있습니다.
defined( identifier )
정의된 식별자
식별자가 현재 정의된 경우 이 상수 식은 true(0이 아닌)로 간주됩니다. 그렇지 않으면 조건은 false(0)입니다. 빈 텍스트로 정의된 식별자는 정의된 것으로 간주됩니다. 정의된 연산자는 #if 및 #elif 지시문에서 사용할 수 있지만 다른 곳에서는 사용할 수 없습니다.
다음 예제 에서 #if 및 #endif 지시문은 세 가지 함수 호출 중 하나의 컴파일을 제어합니다.
#if defined(CREDIT)
credit();
#elif defined(DEBIT)
debit();
#else
printerror();
#endif
credit
식별자가 정의된 경우 CREDIT
에 대한 함수 호출이 컴파일됩니다. DEBIT
식별자가 정의된 경우 debit
에 대한 함수 호출이 컴파일됩니다. 식별자가 정의되지 않은 경우에는 printerror
에 대한 호출이 컴파일됩니다. 둘 다 CREDIT
C 및 credit
C++의 고유 식별자입니다. 해당 사례는 서로 다르기 때문입니다.
다음 예제의 조건부 컴파일 문은 DLEVEL
이라는 이전에 정의된 기호화된 상수를 가정합니다.
#if DLEVEL > 5
#define SIGNAL 1
#if STACKUSE == 1
#define STACK 200
#else
#define STACK 100
#endif
#else
#define SIGNAL 0
#if STACKUSE == 1
#define STACK 100
#else
#define STACK 50
#endif
#endif
#if DLEVEL == 0
#define STACK 0
#elif DLEVEL == 1
#define STACK 100
#elif DLEVEL > 5
display( debugptr );
#else
#define STACK 200
#endif
첫 번째 #if 블록은 중첩된 #if, #else 및 #endif 지시문의 두 집합을 보여 줍니다. DLEVEL > 5
가 true인 경우에만 지시문의 첫 번째 집합이 처리됩니다. 그렇지 않으면 #else 이후의 문이 처리됩니다.
두 번째 예제의 #elif 및 #else 지시문은 값 DLEVEL
에 따라 네 가지 선택 항목 중 하나를 만드는 데 사용됩니다. STACK
상수는 DLEVEL
의 정의에 따라 0, 100 또는 200으로 설정됩니다. DLEVEL
이 5보다 크면 다음 문이
#elif DLEVEL > 5
display(debugptr);
은 컴파일되고 STACK
정의되지 않습니다.
조건부 컴파일은 동일한 헤더 파일이 여러 번 포함되는 것을 방지하기 위해 일반적으로 사용됩니다. 클래스가 헤더 파일에 정의되는 경우가 많은 C++에서는 다음과 같은 구문을 사용하여 여러 정의를 방지할 수 있습니다.
/* EXAMPLE.H - Example header file */
#if !defined( EXAMPLE_H )
#define EXAMPLE_H
class Example
{
//...
};
#endif // !defined( EXAMPLE_H )
앞의 코드에서는 기호화된 상수 EXAMPLE_H
가 정의되어 있는지 여부를 확인합니다. 그렇다면 파일이 이미 포함되어 있으며 다시 처리할 필요가 없습니다. 정의되어 있지 않은 경우에는 EXAMPLE_H
상수가 이미 처리된 대로 EXAMPLE.H를 표시하도록 정의됩니다.
__has_include
Visual Studio 2017 버전 15.3 이상: 라이브러리 헤더를 포함할 수 있는지 여부를 결정합니다.
#ifdef __has_include
# if __has_include(<filesystem>)
# include <filesystem>
# define have_filesystem 1
# elif __has_include(<experimental/filesystem>)
# include <experimental/filesystem>
# define have_filesystem 1
# define experimental_filesystem
# else
# define have_filesystem 0
# endif
#endif