Árvore de páginas

Você está vendo a versão antiga da página. Ver a versão atual.

Comparar com o atual Ver Histórico da Página

« Anterior Versão 5 Atual »

Sintaxis

 

#define <constante> [ <texto de sustitución> ]

#define <función> ( [ <lista de argumentos> ] ) [ < expresión > ]

 

 

Propósito

 

La directiva #define determina una constante o una pseudofunción para el compilador.

 

 

Argumentos

 

<constante>

 

Define el nombre de la constante.

 

<texto de substituição>

 

Opcionalmente, se puede definir un texto para sustituir una constante válida, siempre y cuando el compilador la encuentre.

 

<função>

 

Define el nombre de una pseudofunción con una lista opcional de argumentos. La función siempre debe estar seguida por un abre paréntesis, sin ningún espacio en blanco entre si. La lista de argumentos, si existe, siempre debe estar seguida por un cierra paréntesis, sin espacios en blanco entre sí. Si la lista de argumentos no existe, la función debe estar seguida por un abre y cierra paréntesis, sin espacios en blanco.

 

<lista de argumentos>

 

Define la lista de argumentos de la función separándolos con comas.

 

<expressão>

 

Define la expresión que sustituirá la pseudofunción definida, siempre y cuando el compilador la encuentre. Esta expresión debe estar entre paréntesis para garantizar la precedencia de su evaluación cuando la pseudofunción se expanda.

 

 

Utilización

 

Esta directiva define un nombre identificador y, opcionalmente, le vincula un texto de sustitución. Si se especifica el texto de sustitución el compilador sustituirá la constante por el texto, siempre y cuando la encuentre en una línea del código fuente del archivo de programa (PRW), en la que se definió.

 

Los nombres identificadores especificados por medio de la directiva #define siguen casi todas las reglas de nomenclatura de variables del AdvPL. La principal excepción es que los identificadores definidos por la directiva #define son case-sensitives, es decir, diferencian letras mayúsculas de minúsculas. Por lo tanto, el identificador ident1, por ejemplo, es diferente del identificador IDENT1.

 

Por convención, los identificadores definidos por la directiva #define siempre se especifican con letras mayúsculas, para que se distingan de los demás identificadores de un programa. Además, se acuerda también que los identificadores #define se inician con una o dos letras estandarizadas como prefijo, con el objetivo de agrupar determinados tipos de identificadores, además de garantizar a su unidad.

 

El archivo encabezado PROTHEUS.CH, contenido en el directorio INCLUDE abajo del directorio raíz del Protheus, es un buen ejemplo de como utilizar la directiva #define para determinar identificadores que facilitan el uso de diversas funciones estándar del AdvPL.

 

Cada definición hecha por la directiva #define debe ocurrir aisladamente en una línea de instrucción. Aunque una sola definición (ODR-One Definition Rule) pueda ser continuada por diversas líneas físicas, por medio del punto y coma, el AdvPL no permite que una sola línea lógica de instrucción contenga más de una directiva #define. Cada directiva #define se debe colocar en una línea de instrucción propia, que debe ser seguida por uno o más espacios en blanco, o tabulaciones, así como por un único nombre identificador y opcionalmente por el texto de sustitución. Mientras tanto, las definiciones se pueden intercalar. Es decir, un identificador puede definir otro.

 

Un identificador definido por medio de la directiva #define es válido sólo para las funciones contenidas en el archivo de programa (PRW) en el que se definió. Una vez definido, el identificador se hace visible a partir de la línea de instrucción que lo definió hasta la última línea del archivo de programa (PRW) o hasta que se anule por medio de la directiva #undef, o incluso hasta que se redefina.

 

Los identificadores ya definidos por la directiva #define se podrán anular o  redefinir. Para redefinirlos, basta ejecutar una nueva directiva #define con el mismo nombre identificador, atribuyéndole un nuevo texto de sustitución. En este caso se mostrará un mensaje de advertencia del compilador. Sin embargo, ésta no sustituirá un error, sino tan sólo un aviso para llamar la atención sobre la redefinición efectuada..

 

Para anular un identificador se debe utilizar la directiva #undef, que tiene como argumento el nombre del identificador que se anulará.

 

La directiva #define posee tres propósitos básicos:

 

  1. Definir un identificador de control para las directivas #ifdef y #ifndef.
  2. Definir una constante, es decir, un identificador para representar un valor constante dentro del programa.
  3. Definir una pseudofunción para el compilador.

 

Identificadores para el compilador

 

Este tipo de identificador se define por medio de la directiva #define sin la especificación del texto de substitución. Por lo general se utiliza en la prueba de existencia de un identificador efectuado por las directivas #ifdef y #ifndef.

Estas directivas permiten la determinación de compilaciones condicionales, basadas en la existencia o no de un identificador, causando la inclusión o la eliminación de un determinado trecho del código fuente en el proceso de compilación.

 

 

Constantes

 

En este caso, la directiva #define se utiliza para atribuir un nombre identificador para un determinado valor constante que utilizará el programa. Cada vez que este idenficador sea encontrado por el compilador en una línea del programa, se sustituirá por el valor constante especificado. A continuación vea un ejemplo de la utilización típica de este tipo de identificador:

 

#define K_ESC     27

     ...

     <instrucciones>

     ...

 

IF LASTKEY() == K_ESC

          RETURN

ENDIF

 

En este ejemplo, el identificador K_ESC representa el valor constante 27, que corresponde al código de la función INKEY() para la tecla <Esc>. Por lo tanto, cuando el compilador encuentre al identificador K_ESC, éste lo sustituirá por el valor constante 27, que se procesará efectivamente durante la ejecución del programa.

 

Aunque este tipo de problema se pueda solucionar por medio de la utilización de variables de memoria normales para almacenar los valores constantes, hay una serie de ventajas en la utilización de identificadores definidos por la directiva #define para la representación de valores constantes. Entre estas ventajas podemos citar:

 

  • El compilador genera un código más compacto y más rápido.
  • El programa utilizará menos memoria durante su ejecución.
  • El programa se ejecutará con más rapidez.
  • No volverá a ocurrir un error conceptual que por lo general se comete cuando se usa una variable para almacenar un valor constante.
  • El AdvPL suministra una serie de archivos de encabezado (header files) que ya definen un conjunto de identificadores para representar los valores constantes utilizados por diversas funciones. La inclusión de estos archivos de encabezado, por medio de la directiva #include, facilita mucho la utilización de las funciones en términos de programación.
  • La clareza y legibilidad de los programas se mejora sensiblemente con el uso de identificadores que siguen las convenciones de los archivos de encabezado definidos por el AdvPL. Por ejemplo, en lugar de memorizar todos los códigos de las teclas es mejor leer los identificadores: K_ESC en vez de 27, K_RETURN en vez de 13, y así por delante.
  • El mantenimiento de los programas queda más rápido, puesto que la definición de los identificadores de constantes se encuentra en un mismo punto.
  • Las definiciones de los identificadores de constantes y de otros identificadores se pueden agrupar en archivos específicos: los archivos de encabezado. Estos se pueden incluir en un determinado programa por medio de la directiva #include, permitiendo que las mismas definiciones sean utilizadas por diversos programas, grupos de programas o aplicaciones enteras. Esta técnica genera una mayor estandarización, organización y optimización de su código fuente.
  • La utilización de identificadores para constantes hace que el programa sea más cada vez menos dependiente de su entorno operativo e incluso de su equipo utilizado.

 

Pseudofunciones

 

La directiva #define también puede definir las pseudofunciones durante la etapa de compilación. Una pseudofunción corresponde básicamente a un identificador que se sustituye por una expresión. Por ejemplo:

 

#define RCUB(nX)                      (nX ^ 1 / 3)                    // Raiz cúbica

#define ARET(nLarg, nComp)     (nLarg * nComp)          // Área de un rectángulo

#define ATRI(nBase, nAltura)     (nBase * nAltura / 2)     // Área de un triángulo

 

Durante la etapa de compilación, cuando el compilador encuentra la llamada a una función que coincide con la definición de una pseudofunción, éste sustituye la pseudofunción por la expresión correspondiente. Por ejemplo:

 

MSGALERT( RCUB(9) )          // Se sustituye por (9 ^1 / 3)

MSGALERT( ARET(5, 10) )     // Se sustituye por (5 * 10)

MSGALERT( ATRI(10, 5) )      // Se sustituye por (10 * 5 / 2)

 

Al utilizar la directiva #define en la definición de pseudofunciones y al utilizar las pseudofunciones definidas, algunas reglas se deben observar:

 

  1. La expresión que corresponde a la función y suministra su resultado se debe especificar entre paréntesis.
  2. Cuando se utilizan pseudofunciones, todos los argumentos se deben especificar obligatoriamente.
  3. El nombre de las pseudofunciones se diferencia por la utilización de letras mayúsculas o minúsculas (case sensitive). Por ejemplo, se definió la pseudofunción RCUB, pero rcub no existe.

 

Las pseudofunciones se deben utilizar con cuidado y profesionalismo. Aunque se optimizó el código ejecutable, éstas dificultarán el mantenimiento de los programas, puesto que tienen un enfoque diferente de las funciones normales: son case sensitive y no permiten la omisión de argumentos. Por estos motivos, en la mayoría de los casos se debe dar preferencia a la utilización de funciones de usuario normales o a la definición de pseudofunciones por medio de la directiva #translate. En este último caso, las ventajas en términos de optimización del código se mantienen, la nomenclatura de las pseudofunciones seguirá las reglas normales del AdvPL y los argumentos se podrán omitir.

  • Sem rótulos