Conditional Compilation
Conditional Compilation allows to change the way code is generated using 'Preprocessor commands'.
The '#define' command allows to define compilation constants, that is constants that describe the parameters of the platform for which the program is compiled.
These constants make it possible to carry out conditional compilations, that is to say to modify the behavior of the program according to parameters defined during its compilation.
The '#define' command is also used to replace identifiers of the program with other identifiers, for example to test several versions of the same function without modifying the entire program.
Compilation constants
A clear distinction will be made between compilation constants defined with the '#define' directive of the preprocessor and the constants defined with the 'const' keyword.
Indeed, the literal constants do not reserve memory. These are immediate values, defined by the compiler.
On the other hand, the 'const' can still have a reserved memory space. This is for example the case when manipulating string literals.
A literal constant declared with the '#define' directive of the preprocessor will always retain its value (provided that it is not redefined). These literal constants have no type, which can be very annoying and error-prone in code.
Their use will be reserved for compilation constants only, and the 'const' keyword will be preferred for all other constants of the program.
The preprocessor sets a number of built-in constants automatically.
These are the 'Intrinsic Defines' (see their list).
Indeed, the literal constants do not reserve memory. These are immediate values, defined by the compiler.
On the other hand, the 'const' can still have a reserved memory space. This is for example the case when manipulating string literals.
A literal constant declared with the '#define' directive of the preprocessor will always retain its value (provided that it is not redefined). These literal constants have no type, which can be very annoying and error-prone in code.
Their use will be reserved for compilation constants only, and the 'const' keyword will be preferred for all other constants of the program.
The preprocessor sets a number of built-in constants automatically.
These are the 'Intrinsic Defines' (see their list).
Conditional compilation
The definition of identifiers and compilation constants is widely used to perform so-called conditional compilation.
Conditional compilation consists of replacing certain portions of source code with others, depending on the presence or value of compilation constants.
This is achievable using conditional compilation directives.
The most common of which are probably:
There are other conditional compilation directives like:
This prevents the text from being included multiple times, as a result of multiple #include calls.
Indeed, at the first call, AlreadyThere is not known to the preprocessor. It is therefore declared and the text is included.
On any subsequent call, AlreadyThere exists, and the text is not included.
This kind of writing is found in header files, for which in general we do not want a multiple inclusion to take place.
Conditional compilation consists of replacing certain portions of source code with others, depending on the presence or value of compilation constants.
This is achievable using conditional compilation directives.
The most common of which are probably:
There are other conditional compilation directives like:
- #ifndef (if not defined ...)
- #else / #elseif (otherwise ... / otherwise, if ...)
- #if (if ...)
Another common application of compilation directives is the protection of header files against multiple inclusions:- #else / #elseif (otherwise ... / otherwise, if ...)
- #if (if ...)
the #if directive expects a constant expression as parameter (the text that follows is included in the file if and only if this expression is true).
This prevents the text from being included multiple times, as a result of multiple #include calls.
Indeed, at the first call, AlreadyThere is not known to the preprocessor. It is therefore declared and the text is included.
On any subsequent call, AlreadyThere exists, and the text is not included.
This kind of writing is found in header files, for which in general we do not want a multiple inclusion to take place.
Example
Example of conditional compilation using the Intrinsic define __FB_DEBUG__ to debug a recursive function:
Output after compiling with -g option:
See also
Function recursiveFactorial (ByVal n As Integer) As Integer
If (n = 0) Then '' end condition
#if __FB_DEBUG__ <> 0
Print "end of recursion and result:";
#endif
Return 1
Else '' recursion loop
#if __FB_DEBUG__ <> 0
Print "multiply by: " & n
#endif
Return n * recursiveFactorial(n - 1) '' recursive call
End If
End Function
Print recursiveFactorial(5)
Sleep
Output after compiling without -g option:If (n = 0) Then '' end condition
#if __FB_DEBUG__ <> 0
Print "end of recursion and result:";
#endif
Return 1
Else '' recursion loop
#if __FB_DEBUG__ <> 0
Print "multiply by: " & n
#endif
Return n * recursiveFactorial(n - 1) '' recursive call
End If
End Function
Print recursiveFactorial(5)
Sleep
120
multiply by: 5 multiply by: 4 multiply by: 3 multiply by: 2 multiply by: 1 end of recursion and result: 120
Back to Programmer's Guide