#define
 Define una constante declarada o una pseudofunción
------------------------------------------------------------------------------
 Sintaxis

     #define <idConstante> [<textoResultado>]
     #define <idFunción>([<lista arg>]) [<exp>]

 Argumentos

     <idConstante> es el nombre del identificador que se va a definir.

     <textoResultado> es el texto opcional de sustitución que se escribe
     cada vez que se encuentra un <idConstante> válido.

     <idFunción> es una definición de pseudofunción con una lista
     opcional de argumentos (<lista arg>). Si incluye <lista arg>, debe
     escribirlo entre paréntesis inmediatamente después de <idFunción>.

     <exp> es la expresión de sustitución que se escribe cada vez que se
     encuentra la pseudofunción. Escriba esta expresión entre paréntesis
     para garantizar la prioridad en la evaluación cuando se sustituya la
     pseudofunción en una expresión.

     Nota: Los identificadores #define distinguen letras mayúsculas y
     minúsculas, a diferencia de los identificadores #command y #translate.

 Descripción

     La directiva #define define un identificador y, opcionalmente, le
     asocia una cadena de texto de sustitución. Si se especifica, el texto
     de sustitución funciona de manera análoga a la función de búsqueda y
     sustitución de un editor de texto. Cuando el preprocesador lee cada
     línea del fichero del programa, busca identificadores en ellas. Si
     encuentra alguno de ellos definido, lo reemplaza por el texto de
     sustitución.

     Los identificadores especificados con #define siguen la mayoría de las
     reglas de denominación de identificadores de CA-Clipper. Los
     identificadores definidos pueden contener cualquier combinación de
     caracteres alfanuméricos, incluidos caracteres de subrayado. Los
     identificadores definidos, no obstante, difieren de los demás
     identificadores en que distinguen entre letras mayúsculas y minúsculas,
     pero generalmente se especifican en mayúsculas para diferenciarlos de
     otros identificadores en el programa. Además, los identificadores
     llevan un prefijo de una o dos letras para agrupar identificadores
     similares y garantizar su exclusividad. Para ver algunos ejemplos,
     consulte alguno de los ficheros de cabecera que se encuentran en el
     directorio \CLIP53\INCLUDE.

     Cada definición debe ocupar una línea. A diferencia de las sentencias,
     no puede especificarse más de una directiva en la misma línea. Si
     desea continuar una definición en la línea siguiente, utilice un punto
     y coma (;). Cada directiva #define se especifica seguida de uno o más
     caracteres de espacio en blanco (espacios o tabuladores), un
     identificador exclusivo y un texto opcional de sustitución. Pueden
     anidarse definiciones, lo que permite definir un identificador dentro
     de otro.

     Un identificador definido tiene un ámbito lexicográfico similar al de
     una variable estática en todo el fichero. Sólo es válido en el módulo
     fuente (.prg) en el que se define, a menos que se encuentre en el
     fichero Std.ch o en el fichero de cabecera especificado en la línea de
     mandatos del compilador con la opción /U. A diferencia de las variables
     estáticas en todo el fichero, un identificador definido es visible
     desde el punto en el que se define en el programa hasta que se elimine
     su definición se cambie su definición o se alcance el final del fichero
     del programa.

     Es posible anular o modificar la definición de los identificadores
     existentes. Para redefinir un identificador, especifique una nueva
     directiva #define con el identificador y el nuevo texto de sustitución
     como argumento. La definición actual se sobreeescribe con la nueva
     definición y el compilador muestra un mensaje de advertencia en caso de
     que se redefina el identificador involuntariamente. Para anular la
     definición de un identificador, especifique la directiva #undef con el
     identificador como argumento. Las directivas #define tienen tres
     objetivos principales:

      Definir un identificador de control para #ifdef y #ifndef.

      Definir una constante declarada (un identificador definido
        para representar un valor constante).

      Definir una pseudofunción del compilador.

     La siguiente descripción detalla estos tres objetivos de la directiva
     #define.

 Identificadores del prepocesador

     La mayoría de las directivas #define básicas definen un identificador
     sin texto de sustitución. Puede usar este tipo de identificador si
     necesita comprobar la existencia de un identificador con las directivas
     #ifdef o #ifndef. Esto es útil para incluir o excluir código en una
     compilación condicional. Ese tipo de identificador puede definirse
     también utilizando la opción /D del compilador en la línea de mandatos.
     Consulte los ejemplos siguientes.

 Constantes declaradas

     La segunda forma de una directiva #define asigna un nombre a un valor
     constante. Esta forma de identificador se conoce como constante
     declarada. Por ejemplo, puede definir una constante declarada para el
     código INKEY() asociado a la pulsación de una tecla:

     #define T_ESC...27
     IF LASTKEY() = T_ESC
        .
        . <sentencias>
        .
     ENDIF

     Cuando el preprocesador encuentra una constante declarada al leer una
     línea del programa fuente, la reemplaza con el texto de sustitución
     especificado.

     Aunque también puede hacer esto definiendo una variable, algunas
     ventajas aconsejan utilizar constantes declaradas: el compilador genera
     más rápidamente código más compacto para constantes que para variables;
     las variables tienen asignación general de memoria mientras que las
     constantes declaradas no tienen asignación general de ejecución, lo que
     permite ahorrar memoria y aumentar la velocidad de ejecución. Además,
     utilizar una variable para representar un valor constante es
     conceptualmente incongruente. Una variable cambia por naturaleza y una
     constante no.

     Conviene utilizar constantes declaradas en lugar de constantes por
     varias razones. Primero, mejora la legibilidad. En el ejemplo anterior,
     la constante declarada indica más claramente la tecla representada que
     el propio código INKEY(). Segundo, las constantes declaradas localizan
     la definición de los valores constantes, lo que facilita la realización
     de cambios y aumenta la fiabilidad. Tercero, como un efecto secundario
     de la segunda razón, las constantes declaradas aíslan la implementación
     o las características del entorno cuando se representan como valores
     constantes.

     Si desea aislar más los efectos del cambio, puede agrupar las
     constantes declaradas y otros identificadores en ficheros de cabecera,
     lo que permite compartir identificadores entre ficheros de programa
     (.prg), aplicaciones y grupos de programadores. Con esta metodología,
     pueden crearse definiciones estándar en todo un departamento de
     desarrollo de software. Puede fusionar los ficheros de cabecera con el
     programa actual utilizando directivas #include.

     Si desea ver ejemplos de ficheros de cabecera, consulte los ficheros de
     cabecera del directorio \CLIP53\INCLUDE.

 Pseudo-funciones del compilador

     Además de definir constantes como valores, la directiva #define puede
     también definir pseudofunciones que se resuelven durante la
     compilación. Una definición de pseudofunción es un identificador
     seguido inmediatamente por una lista de argumentos, escrita entre
     paréntesis, y el texto de sustitución. Por ejemplo:

     #define AREA(nLonj, nAnchura)        (nLonj * nAnchura)
     #define DARVALOR(x, y)               (x := y)
     #define MAX(x, y)                    (IF(x > y, x, y))

     Las pseudofunciones difieren de las constantes declaradas en que
     admiten argumentos. Cuando el preprocesador lee las líneas del módulo
     fuente y encuentra una llamada a una función que corresponde a la
     definición de pseudofunción, sustituye la llamada a la función por la
     expresión de sustitución. Los argumentos de la llamada de la función se
     llevan a la expresión de sustitución mediante los nombres especificados
     en la lista de argumentos de la definición del identificador. Cuando la
     expresión de sustitución se sustituye por la pseudofunción, los nombres
     de la expresión de sustitución se cambian por el texto de argumentos.
     Por ejemplo, las siguientes invocaciones:

     ? AREA(10, 12)
     DARVALOR(nValor, 10)
     ? MAX(10, 9)

     se sustituyen por:
     ? (10 * 12)
     nValor := 10
     ? (IF(10 > 9, 10, 9))

     Cuando se definen pseudofunciones, es importante escribir la expresión
     resultante entre paréntesis para forzar el orden de evaluación adecuado
     de los argumentos. Esto es especialmente importante en expresiones
     numéricas. En las pseudofunciones, es necesario especificar todos los
     argumentos. De lo contrario, la llamada a la función no se amplía como
     una pseudofunción y pasa inalterada del preprocesador al compilador.

     Las pseudofunciones no requieren la asignación general de una llamada
     de función, por lo que suelen ser más rápidas. También utilizan menos
     memoria. No obstante, son más difíciles de depurar con el depurador,
     tienen un ámbito diferente de las funciones y procedimientos
     declarados, no permiten saltar argumentos y diferencian letras
     mayúsculas y minúsculas.

     Puede evitar algunos de estos inconvenientes de las pseudofunciones con
     la directiva #translate. De este modo, no se diferencian mayúsculas y
     minúsculas, se aceptan argumentos opcionales y se sigue la regla de
     cuatro letras de dBase. Si desea más información, consulte la directiva
     #translate.

 Ejemplos

      En este ejemplo, una constante declarada controla
        condicionalmente la compilación del código de depuración:

        #define DEPURADO
        .
        . <sentencias>
        .
        #ifdef DEPURADO
           Confirmar(FILE("System.dbf"))
        #endif

      Este ejemplo define una constante declarada y la sustituye por
        un valor INKEY():

        #define T_ESC        27
        .
        . <sentencias>
        .
        IF INKEY() != T_ESC
           Hacerlo()
        ELSE
           Pararlo()
        ENDIF

      Este ejemplo define pseudofunciones para las funciones
        estándar de CA-Clipper, MAX() y ALLTRIM():

        #define MAX(arg1, arg2)        (IF(arg1 > arg2, ;
           arg1, arg2))
        #define ALLTRIM(cCadena)   (RTRIM(LTRIM(cCadena)))
        .
        . <sentencias>
        .
        ? MAX(1, 2)
        ? ALLTRIM(" Hola ")

 To download this example - click here.

See Also: #command #ifdef #ifndef #undef #xcommand