¡Nuevo!  por fin disponible la versión 5 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


Directivas  #if,  #elif,  #else,  #endif

§1  Sinopsis

C++ ofrece la posibilidad de compilación condicional mediante la inclusión de ciertas directivas que controlan el comportamiento del preprocesador, de forma que este puede ignorar o compilar determinadas líneas del código en función de ciertas condiciones que son evaluadas durante el preproceso.

§2  Sintaxis

#if k-expresion-1
   <seccion-1>
<#elif k-expresion-2
   <seccion-2>

 ...
 
<#elif k-expresion-n
   <seccion-n>
<#else
   <seccion-final>
#endif

§3  Comentario

Las directivas condicionales #if, #elif, #else  y #endif se comportan igual que las sentencias C/C++ de selección ( 4.10.2). Si k-expresion-1 -sujeta a posible macro-expansión- es cierta (distinto de cero), las líneas de código de seccion-1, que pueden estar vacías, ser líneas normales de código o incluso de preprocesado, son preprocesadas y pasadas al compilador. Si es falsa (cero), la seccion-1 es ignorada por completo.

En el caso de ser cierta, después que se ha procesado la seccion-1, el control pasa a la correspondiente #endif, con lo que se termina la sentencia condicional y se continúa con la sección siguiente. Si es falsa, el control pasa a la siguiente #elif, donde se evalúa k-expresion-2. Si es cierta, se procesa la seccion-2, tras lo cual el control pasa al correspondiente #endif. En caso contrario, si k-expresion-2 es falsa, el control pasa al siguiente #elif. Así sucesivamente hasta que se llega a algún #else o #endif (#else es opcional y se alcanza si todas las comprobaciones previas han sido falsas).

Las diferentes secciones pueden contener a su vez otras cláusulas condicionales anidadas en cualquier profundidad. Cada #if debe contar con su correspondiente #endif. Puede haber cualquier número de #elif, pero solo un #else (que debe ser el último).


§4  Las expresiones k-expresion-n deben evaluarse a una constante entera. Es decir, debe ser una expresión constante que se reduzca a un entero, aunque esta expresión puede tener ciertas restricciones ( 3.2.3a).

Ejemplo

#if SYSTEM == SYSV
    #define HDR "sysv.h"
#elif SYSTEM == BSD
    #define HDR "bsd.h"
#elif SYSTEM == MSDOS
    #define HDR "msdos.h"
#else
    #define HDR "default.h"
#endif
#include HDR            // incluir la cabecera adecuada.

En este caso, se supone que SYSV, BSD y MSDOS son constantes simbólicas que en algún punto están definidas como valores enteros. A su vez SYSTEM es igualmente una constante simbólica cuyo valor es un entero.


Nada impide que la expresión condicional sea a su vez una expresión compuesta, tal como se muestra en el siguiente ejemplo tomado de un caso real de programación Windows.

#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) ||  defined(__WXX11__)
    #include "mondrian.xpm"
#endif

En este caso los nombres en mayúsculas corresponden a constantes manifiestas ( 1.4.1a) definidas en distintos compiladores C++. Ver ejemplos adicionales en  4.9.10c y 1.4.


El ejemplo siguiente muestra unas sentencias de compilación condicional en función del valor de la constante simbólica DLEVEL que se supone ha sido definida previamente.

#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

El primer bloque #if (primeras 15 líneas), contiene dos series de directivas #if, #else y #endif anidadas en él. La primera se procesa si es cierta la condición DLEVEL > 5. En caso contrario se procesa la serie situada después del #else.

El resto de líneas del ejemplo se utiliza para establecer el valor de la constante STACK a 0, 100 o 200 en función del valor de la constante DLEVEL, pero si su valor es mayor que 5, STACK queda indefinida, y en su lugar se compila una invocación a la función display utilizando debugptr como argumento.

§5  Operador defined

Tanto Borland C++ como MS VC++ disponen de este operador [1] que solo puede ser utilizado en conjunción con las directivas #if y #elif. Admite dos formas de sintaxis, una de ellas con aspecto de función:

#if   defined ( <identificador> )
#if   defined <identificador>
#elif defined ( <identificador> )
#elif defined <identificador>

§5.1  Descripción

Este operador devuelve cierto (distinto de cero) si identificador ha sido definido previamente mediante una directiva #define ( 4.9.10b). En caso contrario devuelve falso (0).

Como puede verse, cumple la misma función que la directiva #ifdef, de forma que las dos expresiones que siguen son equivalentes:

#if defined identificador
#ifdef identificador

Sin embargo, el operador tiene la ventaja de que permite construir expresiones más complejas en la misma directiva #if o #elif.  Por ejemplo:

#if defined(identif1) && !defined(identifi2)
...
#elif defined(identif1) && defined(identifi2)
...

En el ejemplo siguiente, se utiliza el operador para controlar la compilación de una función entre tres posibilidades:

#if defined(CLIENTE)
  cliente();
#elif defined(PROVEEDOR)
  proveedor();
#else
  printerror();
#endif

Si el identificador CLIENTE ha sido definido, se compila una llamada a la función cliente(). En caso contrario, si se ha definido el identificador PROVEEDOR, se compila una invocación a la función proveedor(); finalmente, en ausencia de alguna de las condiciones anteriores, se invoca la función printerror().

Es frecuente que este operador se utilice para formar directivas de guarda ( 4.9.10e)

  Inicio.


[1]  No incluído en el Estándard C++