Namespaces
Variants

Conditional inclusion

From cppreference.net

전처리기는 소스 파일의 일부를 조건부로 컴파일하는 기능을 지원합니다. 이 동작은 #if , #else , #elif , #ifdef , #ifndef , #elifdef , #elifndef (C23 이후) , 그리고 #endif 지시자에 의해 제어됩니다.

목차

구문

#if 표현식
#ifdef 식별자
#ifndef 식별자
#elif 표현식
#elifdef 식별자 (C23 이후)
#elifndef 식별자 (C23 이후)
#else
#endif

설명

조건부 전처리 블록은 #if , #ifdef 또는 #ifndef 지시자로 시작하며, 선택적으로 임의의 수의 #elif , #elifdef , 또는 #elifndef (C23부터) 지시자를 포함할 수 있고, 선택적으로 최대 하나의 #else 지시자를 포함하며, #endif 지시자로 종료됩니다. 내부의 모든 조건부 전처리 블록은 별도로 처리됩니다.

다음 각 지시문들 #if , #ifdef , #ifndef , #elif , #elifdef , #elifndef (C23부터) , 그리고 #else 는 첫 번째 #elif , #elifdef , #elifndef (C23부터) , #else , #endif 지시문이 나올 때까지 코드 블록을 제어합니다. 단, 이는 내부 조건부 전처리 블록에 속하지 않는 지시문에 한합니다.

#if , #ifdef #ifndef 지시자는 지정된 조건(아래 참조)을 검사하고 조건이 true로 평가되면 제어되는 코드 블록을 컴파일합니다. 이 경우 후속 #else , #elifdef , #elifndef , (C23부터) #elif 지시자는 무시됩니다. 반대로 지정된 조건이 false로 평가되면 제어되는 코드 블록은 건너뛰고 후속 #else , #elifdef , #elifndef , (C23부터) 또는 #elif 지시자(있는 경우)가 처리됩니다. 후속 지시자가 #else 인 경우, #else 지시자에 의해 제어되는 코드 블록은 무조건 컴파일됩니다. 그렇지 않으면 #elif , #elifdef , 또는 #elifndef (C23부터) 지시자는 #if 지시자인 것처럼 동작합니다: 조건을 확인하고, 결과에 따라 제어되는 코드 블록을 컴파일하거나 건너뛰며, 후자의 경우 후속 #elif , #elifdef , #elifndef , (C23부터) #else 지시자를 처리합니다. 조건부 전처리 블록은 #endif 지시자로 종료됩니다.

조건부 평가

#if, #elif

표현식 은 상수 표현식으로, 상수 #define 지시문을 사용하여 정의된 식별자만 사용합니다. 리터럴이 아니고 #define 지시문을 사용하여 정의되지 않은 모든 식별자는 0 으로 평가되며, true 1 로 평가되는 경우는 예외입니다 (C23부터) .

표현식은 다음과 같은 형태의 단항 연산자를 포함할 수 있습니다: defined identifier 또는 defined ( identifier ) 이 연산자들은 identifier #define 지시자를 사용하여 정의된 경우 1 을 반환하고, 그렇지 않으면 0 을 반환합니다. 이 문맥에서 __has_include , __has_embed __has_c_attribute 는 정의된 매크로 이름처럼 취급됩니다. (C23부터) 만약 expression 이 0이 아닌 값으로 평가되면 제어되는 코드 블록이 포함되고, 그렇지 않으면 건너뜁니다. 사용된 식별자가 상수가 아닌 경우 0 으로 대체됩니다.

전처리기 지시문의 맥락에서, __has_c_attribute 표현식은 주어진 속성 토큰이 지원되는지와 지원되는 버전을 감지합니다. 자세한 내용은 속성 테스트 를 참조하십시오.

(C23부터)

참고: DR 412 이전까지, #if cond1 ... #elif cond2 #if cond1 ... #else 뒤에 #if cond3 가 오는 경우와 다릅니다. 왜냐하면 cond1 가 참일 경우, 두 번째 #if 는 건너뛰어지고 cond3 는 올바른 형식일 필요가 없지만, #elif cond2 는 유효한 표현식이어야 하기 때문입니다. DR 412 부터는 건너뛰어지는 코드 블록을 유도하는 #elif 도 건너뛰어집니다.

결합 지시문

식별자가 매크로 이름으로 정의되었는지 확인합니다.

#ifdef identifier 는 기본적으로 #if defined identifier 와 동등합니다.

#ifndef identifier 는 기본적으로 #if !defined identifier 와 동등합니다.

#elifdef identifier 는 기본적으로 #elif defined identifier 와 동등합니다.

#elifndef identifier 는 기본적으로 #elif !defined identifier 와 동등합니다.

(C23부터)

참고 사항

#elifdef #elifndef 지시문은 C23을 대상으로 하지만, 구현체들은 이를 이전 언어 모드로 이식 가능한 확장 기능으로 제공할 수 있습니다.

예제

#define ABCD 2
#include <stdio.h>
int main(void)
{
#ifdef ABCD
    printf("1: yes\n");
#else
    printf("1: no\n");
#endif
#ifndef ABCD
    printf("2: no1\n");
#elif ABCD == 2
    printf("2: yes\n");
#else
    printf("2: no2\n");
#endif
#if !defined(DCBA) && (ABCD < 2 * 4 - 3)
    printf("3: yes\n");
#endif
// C23 directives #elifdef/#elifndef
#ifdef CPU
    printf("4: no1\n");
#elifdef GPU
    printf("4: no2\n");
#elifndef RAM
    printf("4: yes\n"); // selected in C23 mode, may be selected in pre-C23 mode
#else
    printf("4: no3\n"); // may be selected in pre-C23 mode
#endif
}

가능한 출력:

1: yes
2: yes
3: yes
4: yes

결함 보고서

다음의 동작 변경 결함 보고서들은 이전에 발표된 C 표준에 소급 적용되었습니다.

DR 적용 대상 게시된 동작 올바른 동작
DR 412 C89 실패한 #elif 의 표현식이 유효해야 했음 실패한 #elif 는 건너뜀

참고문헌

  • C23 표준 (ISO/IEC 9899:2024):
  • 6.10.1 조건부 포함 (p: TBD)
  • C17 표준 (ISO/IEC 9899:2018):
  • 6.10.1 조건부 포함 (p: 118-119)
  • C11 표준 (ISO/IEC 9899:2011):
  • 6.10.1 조건부 포함 (p: 162-164)
  • C99 표준 (ISO/IEC 9899:1999):
  • 6.10.1 조건부 포함 (p: 147-149)
  • C89/C90 표준 (ISO/IEC 9899:1990):
  • 3.8.1 조건부 포함

참고 항목

C++ 문서 for 조건부 포함