Does Delphi's conditional compilation allow th

2019-06-24 06:41发布

问题:

In Delphi, you can define symbols, just like in C/C++.

Delphi:

{$DEFINE MY_SYMBOL}

C/C++:

#define MY_SYMBOL

This allows you to check whether the symbol is defined by using {$IFDEF MY_SYMBOL} in Delphi, or #ifdef MY_SYMBOL in C/C++.

This is a boolean value - either the symbol is defined during pre-processing or not. However, C/C++ also allows you to assign values to preprocessor symbols. E.g.:

#ifdef DEBUG
#define DB_HOST "127.0.0.1"
#else
#define DB_HOST "123.456.789.123"
#endif

Database *pDatabase = new Database(DB_HOST);

Is assigning a value to a preprocessor symbol possible in Delphi, or does Delphi only allow you to determine whether or not a symbol has been defined at all?

EDIT: As Delphi doesn't support symbol values in the preprocessor, I'm assuming it doesn't support preprocessor macros. Am I right in this assumption?

For example, in C you can define a preprocessor macro that gets copied and pasted with the appropriate parameters before compilation. This is useful when you want "inline function" capability for fast operations (e.g., binary logic, testing in an integer values, bit-shifting, etc) without the overhead of stack frames, parameter passing and the like.

#define OK_FLAG 0x00000001
#define OK(f) (f & OK_FLAG)

#define WEAK_XOR_CIPHER(v) (v ^ 0xff)

回答1:

You can simply use a constant, and define the value:

const
{$IFDEF DEBUG}
  DB_Host = '127.0.0.1';
{$ELSE}
  DB_Host = '123.45.67.89';
{$ENDIF}

You can also do the reverse (test for something not being defined):

const
{$IFNDEF DEBUG}
  DB_Host = '123.45.67.89';
{$ELSE}
  DB_Host = '127.0.0.1';
{$ENDIF}

This ensures that DB_Host is always available, and has the appropriate value when not debugging.

Recent versions of Delphi allow you to test the value of constants. For instance, the System unit has the constant RTLVersion defined, and you can test for a value using it:

{$IF RTLVersion <= 26}
  // Less than XE5
{$ELSE}
  // XE5
{$IFEND}

Delphi doesn't support macros of any sort, however. The typical solution to not having macros is to use an inline function. See, for instance the Windows unit's implementation of the WinAPI RGB macro:

function RGB(r, g, b: Byte): COLORREF; inline;

function RGB(r, g, b: Byte): COLORREF;
begin
  Result := (r or (g shl 8) or (b shl 16));
end;