Namespaces
Variants

Conditional inclusion

From cppreference.net

El preprocesador admite la compilación condicional de partes del archivo fuente. Este comportamiento se controla mediante las directivas #if , #else , #elif , #ifdef , #ifndef , #elifdef , #elifndef (desde C23) , y #endif .

Contenidos

Sintaxis

#if expresión
#ifdef identificador
#ifndef identificador
#elif expresión
#elifdef identificador (desde C23)
#elifndef identificador (desde C23)
#else
#endif

Explicación

El bloque de preprocesamiento condicional comienza con la directiva #if , #ifdef o #ifndef , luego opcionalmente incluye cualquier número de directivas #elif , #elifdef , o #elifndef (desde C23) , luego opcionalmente incluye como máximo una directiva #else y finaliza con la directiva #endif . Cualquier bloque interno de preprocesamiento condicional se procesa por separado.

Cada una de las directivas #if , #ifdef , #ifndef , #elif , #elifdef , #elifndef (desde C23) , y #else controla un bloque de código hasta la primera directiva #elif , #elifdef , #elifndef (desde C23) , #else , #endif que no pertenezca a ningún bloque de preprocesamiento condicional interno.

#if , #ifdef y #ifndef evalúan la condición especificada (ver abajo) y si se evalúa como verdadera, compilan el bloque de código controlado. En ese caso, las directivas posteriores #else , #elifdef , #elifndef , (desde C23) y #elif se ignoran. De lo contrario, si la condición especificada se evalúa como falsa, se omite el bloque de código controlado y se procesa la directiva posterior #else , #elifdef , #elifndef , (desde C23) o #elif (si existe). Si la directiva posterior es #else , el bloque de código controlado por la directiva #else se compila incondicionalmente. De lo contrario, la directiva #elif , #elifdef , o #elifndef (desde C23) actúa como si fuera una directiva #if : verifica la condición, compila u omite el bloque de código controlado según el resultado, y en este último caso procesa las directivas posteriores #elif , #elifdef , #elifndef , (desde C23) y #else . El bloque de preprocesamiento condicional finaliza con la directiva #endif .

Evaluación condicional

#if, #elif

La expresión es una expresión constante, utilizando únicamente constantes e identificadores definidos mediante la directiva #define . Cualquier identificador que no sea literal, no definido mediante la directiva #define , se evalúa como 0 excepto true que se evalúa como 1 (desde C23) .

La expresión puede contener operadores unarios en la forma defined identificador o defined ( identificador ) que retornan 1 si el identificador fue definido usando la directiva #define y 0 en caso contrario. En este contexto, __has_include , __has_embed y __has_c_attribute se tratan como si fueran nombres de macros definidas. (desde C23) Si la expresión se evalúa como un valor distinto de cero, el bloque de código controlado se incluye y se omite en caso contrario. Si cualquier identificador utilizado no es una constante, se reemplaza con 0 .

En el contexto de una directiva de preprocesador, una expresión __has_c_attribute detecta si un token de atributo dado es compatible y su versión compatible. Consulte Pruebas de atributos .

(desde C23)

Nota: Hasta DR 412 , #if cond1 ... #elif cond2 es diferente de #if cond1 ... #else seguido por #if cond3 porque si cond1 es verdadero, el segundo #if se omite y cond3 no necesita estar bien formado, mientras que #elif 's cond2 debe ser una expresión válida. A partir de DR 412 , #elif que conduce al bloque de código omitido también se omite.

Directivas combinadas

Comprueba si el identificador fue definido como un nombre de macro .

#ifdef identifier es esencialmente equivalente a #if defined identifier .

#ifndef identifier es esencialmente equivalente a #if !defined identifier .

#elifdef identifier es esencialmente equivalente a #elif defined identifier .

#elifndef identifier es esencialmente equivalente a #elif !defined identifier .

(desde C23)

Notas

Mientras que las directivas #elifdef y #elifndef están destinadas para C23, las implementaciones pueden portarlas retroactivamente a los modos de lenguaje más antiguos como extensiones conformes.

Ejemplo

#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
}

Salida posible:

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

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
DR 412 C89 se requería que la expresión de #elif fallido fuera válida el #elif fallido se omite

Referencias

  • Estándar C23 (ISO/IEC 9899:2024):
  • 6.10.1 Inclusión condicional (p: TBD)
  • Estándar C17 (ISO/IEC 9899:2018):
  • 6.10.1 Inclusión condicional (p: 118-119)
  • Estándar C11 (ISO/IEC 9899:2011):
  • 6.10.1 Inclusión condicional (p: 162-164)
  • Estándar C99 (ISO/IEC 9899:1999):
  • 6.10.1 Inclusión condicional (p: 147-149)
  • Estándar C89/C90 (ISO/IEC 9899:1990):
  • 3.8.1 Inclusión condicional

Véase también

Documentación de C++ para Inclusión condicional