Conditional inclusion
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
|
(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
.
|
|
(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
|