The pre-processor is the first stage of the compilation process. It works almost exactly like the C pre-processor for those C programmers out there. It provides definitions and macros which ease both programming tasks and maintenance.
A pre-processor directive is denoted by a # being the first non-whitespace character on a line, followed immediately by the directive on the line. A backslash (‘\’) can be used as the last character on a line to continue the definition on the next line (allowing “multi-line macros”).
Constants are defined by the the #define directive (usage: #define <symbol> <text>) and once a constant has been defined, every instance of that symbol will be replaced with whatever the body text is. For instance, using the directive:
#define HAT_SIZE 10
will cause all instances of “HAT_SIZE” as a complete word (no partial matches) to be replaced with the text “10”. This is useful, for instance, if for some reason in the future, you wished to change HAT_SIZE to be 12 instead of 10. By using a #define, you can only change it in one place, not every place you might have had the number 10.
Macros are just like constants (they use the same directive even) except they may take some parameters. Each parameter in the name, is substituted in the macro body before the entire text as a whole is replaced for the macro call. Let’s see an example.
#define OVERJOYED 10
#define IS_HAPPY(feeling) ( (feeling) > 100 or feeling = OVERJOYED)
Now let’s use the macro.
if( IS_HAPPY(happiness) )then
debugout("I'm happy!\n");
else
debugout("I'm sad...\n");
In the above IF statement, the IS_HAPPY will actually be replaced with the following text. Note how even the constant in the macro body is expanded and replaced properly.
if( ( (happiness) > 100 or happiness = 10 ) )then
debugout("I'm happy!\n'');
else
debugout("I'm sad...\n'');
Although, it’s not really necessary to see what the expanded text is (Indeed. Often it’s quite ugly.) it’s shown here as an example.
A Caveat
There is one caveat when using macros however: choose your parameter names wisely. Take the following for example.
#define WEIGHT(replica) replica[replica].byte[5]
if( WEIGHT(1234) > 10 )then
debugout("Man that's heavy.\n");
It looks fine and is syntactically correct, however, when used it expands to the following.
if( 1234[1234].byte[5] )then
debugout("Man that's heavy.\n");
Note how both instances of “replica” (the parameter name) were replaced in the macro body. This is correct behavior of the pre-processor but not likely the intended usage (1234[1234].byte[5] makes no sense).
Summary
| The pre-processor is the first stage of the compilation process. |
| Here’s a rundown of the directives available to the pre-processor. |
| This recursively includes the entire file specified as if it was actually inserted at the given location. |
| |
| |
| Delete the definition of this constant or macro. |
| Process the following code only if the specified symbol is defined. |
| Just like #ifdef but only process if the symbol is not defined. |
| If inside a conditional directive (#ifdef or #ifndef) and processing, then cease processing until an #endif is encountered. |
| This terminates a conditional directive (or chain of directives). |