Declaración de constante (#define, #undef)

El compilador usa las directivas del preprocesador para procesar de manera preliminar el código fuente antes de proceder a su compilación. La directiva comienza siempre con el símbolo # (almohadilla), por este motivo, el compilador prohíbe utilizar este símbolo en los nombres de las variables, funciones, etcétera.

Cada directiva se describe con una entrada aparte y es válida hasta el salto de línea. No es posible usar varias directivas en una sola entrada. Si la entrada de la directiva es demasiado grande, podremos dividirla en varias líneas con la ayuda de la barra invertida '\', en este caso, la línea siguiente se considerará una continuación de la entrada de la directiva.

La directiva #define puede ser utilizada para la asignación de los nombres mnemotécnicos a las constantes. Hay dos formas:

#define identifier expression                   // forma libre de parámetros
#define identifier(par1,... par8) expression    // forma paramétrica

La directiva #define sustituye todas las siguientes entradas identifier en el texto original por expression. identifier se sustituye sólo en el caso si es un token suelto. identifier no se sustituye si es parte del un comentario, una cadena o parte de otro identificador más largo.

El identificador de constante se rige por las mismas reglas, las que funcionan para los nombres de las variables. El valor puede ser de cualquier tipo:

#define ABC               100
#define PI                3.14
#define COMPANY_NAME      "MetaQuotes Software Corp."
...
void ShowCopyright()
  {
   Print("Copyright  2001-2009, ",COMPANY_NAME);
   Print("https://www.metaquotes.net");
  }

expression puede estar compuesto por varios tokens, como por ejemplo, palabras claves, constantes, expresiones constantes y no constantes. expression se termina con el fin de la línea y no puede saltar a la siguiente.

Ejemplo:

#define TWO        2
#define THREE      3
#define INCOMPLETE TWO+THREE
#define COMPLETE  (TWO+THREE)
void OnStart()
  {
   Print("2 + 3*2 = ",INCOMPLETE*2);
   Print("(2 + 3)*2 = ",COMPLETE*2);
  }
/* Resultado
   2 + 3*2 = 8
   (2 + 3)*2 = 10
*/

 

Forma paramétrica #define

En caso de forma paramétrica, todas las siguientes entradas encontradas del identifier serán reemplazadas por expression, tomando en consideración los parámetros actuales. Por ejemplo,

 // un ejemplo con dos parámetros a y b
#define A 2+3
#define B 5-1
#define MUL(a, b) ((a)*(b))
 
double c=MUL(A,B);
Print("c=",c);
/*
expresión double c=MUL(A,B);
es equivalente a double c=((2+3)*(5-1));
*/
// Resultado
// c=20

Asegúrese de encerrar los parámetros entre paréntesis a la hora de usarlos en expression, porque esto va a permitirle evitar los errores implícitos, difíciles de detectar. Si reescribimos el ejemplo sin utilizar los paréntesis, el resultado será totalmente diferente:

 // un ejemplo con dos parámetros a y b
#define A 2+3
#define B 5-1
#define MUL(a, b) a*b
 
double c=MUL(A,B);
Print("c=",c);
/*
expresión double c=MUL(A,B);
es equivalente a double c=2+3*5-1;
*/
// Resultado
// c=16

Cuando se utiliza la forma paramétrica, se admite el máximo de 8 parámetros.

 // forma paramétrica correcta
#define LOG(text)  Print(__FILE__,"(",__LINE__,") :",text)   // un parámetro - 'text'
 
 // forma paramétrica incorrecta        
#define WRONG_DEF(p1, p2, p3, p4, p5, p6, p7, p8, p9)   p1+p2+p3+p4 // más de 8 parámetros de p1 a p9

Directiva #undef

Directiva #undef sirve para cancelar la macro declarada anteriormente.

Ejemplo:

#define MACRO
 
void func1()
  {
#ifdef MACRO
   Print("MACRO is defined in ",__FUNCTION__);   
#else
   Print("MACRO is not defined in ",__FUNCTION__);
#endif
  }
 
#undef MACRO
 
void func2()
  {
#ifdef MACRO
   Print("MACRO is defined in ",__FUNCTION__);
#else
   Print("MACRO is not defined in ",__FUNCTION__);
#endif
  }
 
void OnStart()
  {
   func1();
   func2();
  }
 
/* Resultado:
 MACRO is defined in func1
 MACRO is not defined in func2
*/

Véase también

Identificadores, Constantes de caracteres