xHarbour Reference Documentation > Preprocessor Reference xHarbour Developers Network  

#define

Defines a symbolic constant or pseudo-function.

Syntax

#define <Constant>                  [<value>]
#define <Function>([<params,...>])  [<expr>]

Arguments

<Constant>
This is the symbolic name of the constant to define. #define constants are case sensitive.
<value>
This is the value all occurances of <Constant> are replaced with in the PRG source code by the preprocessor. If <value> is omitted, <Constant> is removed from the PRG source code.
<Function>
This is the symbolic name of the pseudo function to define. It is case sensitive and must be followed by parentheses.
<params,...>
A comma separated list of parameters can optionally be specified for the pseudo-function.
<expr>
This is the expression the pseudo-function is translated to by the preprocessor. All occurrances of <Function>( <params,...> ) are substituted with <expr>.

Description

One of the most important directives is the #define directive. It is used to define a symbolic name and optionally associate it with a constant value, or to define a pseudo-function. Both, #define constants and pseudo-functions, help a programmer to maintain PRG source code better, and enhance its readability. In addition, #define constants are used for the purpose of conditional compilation in conjunction with the #if, #ifdef and #ifndef directives.

The #define directive is processed by the preprocessor, similar as #command and #translate. The major difference, however, is that #define directives are case sensitive and are coded without the => characters as separators.

Symbolic constants

A common usage for the #define directive is the definition of symbolic constants that are optionally associated with a constant value. By convention, the names of symbolic constants are coded in upper case so they are easily recognized in the PRG source code. When a symbolic constant is associated with a value, the symbolic name of the constant value can be used similar as the usage of a named memory variable. The difference is, that the value of a symbolic constant cannot change at runtime of a program. This is because symbolic constants are resolved by the preprocessor, while memory variables are run-time entities.

The following code example explains the difference between a symbolic constant and a memory variable:

   // PRG code

   #define  K_INS           22
   #define  _SET_INSERT     29

   nKey := Inkey(0)

   IF nKey == K_INS
      Set( _SET_INSERT, .NOT. Set( _SET_INSERT ) )
   ENDIF

This code queries a key press using the Inkey() function. When the user presses the Ins key, the setting for insert/overwrite mode is toggled. The code relies on two symbolic constants, K_ESC and _SET_INSERT, and both have a numeric value associated. This allows a programmer to use a symbolic name for the IF condition and the Set() function call.

The code is processed by the preprocessor. As a result, the compiler processes the following:

   // PPO code

   nKey := Inkey(0)

   IF nKey == 22
      Set(29, .NOT. Set(29 ) )
   ENDIF

A programmer could have coded the preprocessor result in the first place. It is, however, more intuitive for a programmer to use symbolic names in PRG code than to memorize numeric constants for a variety of reasons. It becomes also clear that while nKey, as a memory variable, can change its value later in the program, symbolic #define constants cannot: they are replaced with their associated constant value at compile time.

Pseudo-functions

A #define directive can be coded in functional syntax. Function calls that match with such an directive are translated by the preprocessor and replaced with the result pattern of the directive. The following example illustrates this:

   // PRG code

   #define InRange( val, low, high )   (val >= low .AND. high >= val)

   n     := 10
   nLow  := 5
   nHigh := 11

   IF InRange( n, nLow, nHigh )
      ? "value fits in range"
   ENDIF

The IF condition looks syntactically like a function call accepting three memory variables as arguments. However, there is no function call due to the #define directive. The compiler processes an .AND. expression instead:

   // PPO code

   n := 10
   nLow := 5
   nHigh := 11

   IF (n >= nLow .AND. nHigh  >= n)
      QOut("value fits in range" )
   ENDIF

The usage of pseudo-functions is advantageous when a function call can be coded as a complex one-line expression. This can relieve a programmer from much typing and reduces the size of the resulting executable file since the overhead of a function call can be avoided. Note, however, that the name of the pseudo-function is case-sensitive, and that the function must be coded with the exact number of arguments specified in the #define directive.

Conditional compilation

A third area where #define directives play an important role is conditional compilation. Program code can be compiled in different ways depending on the presence or absence of #define constants and/or their values. This is accomplished in conjunction with the directives #if, #ifdef and #ifndef. Please refer to these topics for examples of Conditional compilation.

Info

See also:#command | #translate, #if, #ifdef, #ifndef, #undef, #xcommand | #xtranslate
Category: Preprocessor directives


Copyright © 2006-2007 xHarbour.com Inc. All rights reserved.
http://www.xHarbour.com
Created by docmaker.exe