Geas MUD, enter the Aventure!
Geas Home | Play the Game

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3.2 The #define statement

This is a very powerful macro or substitute preprocessor command that can be abused endlessly. You are wise if you use it with caution and only for simple tasks.

The syntax is as follows:

#define <pattern> <substitute pattern>
#undef <pattern>

Any text in the file that matches <pattern> will be substituted for <substitute pattern> before compilation occurs. A #define is valid from the line it is found on until the end of the file or an #undef command that removes it.

Although defines can be written just as any kind of text, it is the custom (do this!) to use only capitals when writing them. This is so that they will be easily distinguishable for what they are since no one (not you either!) ever writes function or variable names with capitals.

Place all defines in the beginning of the file, or the poor chum who next tries to look at your code will have the devil's own time of locating them. If it's someone you asked for help (since your badly written code most likely won't work) he probably will tell you to stick the file someplace very unhygienic and come back later when you've learned to write properly.

Simple defines are for example paths, names and above all constants of any kind that you don't want to write over and over.

#define MAX_LOGIN  100          /* Max logged on players */
#define LOGIN_OB   "/std/login" /* The login object      */
#define GREET_TEXT "Welcome!"   /* The login message     */

Wherever the pattern strings above occur, they will be replaced by whatever is followed by the pattern until the end of the line. That includes the comments above, but they are removed anyway later.

tell_object(player, GREET_TEXT + "\n");

A comment on the // form is not a good thing since it doesn't end until the end of the line.

#define GREET_TEXT    "Welcome!"    // The login message

...will be translated into the previous example as:

tell_object(player,    "Welcome!"    // The login message + "\n");

...which will have the effect of commenting away everything after the //, all the way until the end of the line.

If a macro extends beyond the end of the line you can terminate the lines with a \ which signifies that it continues on the next line. However, you must break the string right after the \, there must NOT be any spaces or other characters there, just the line break.

#define LONG_DEFINE  "beginning of string \
                      and end of the same"	

Function-like defines are fairly common and often abused. The only really important rule is that any argument to the macro must be written so that they are used enclosed in parenthesis. If you don't do that you can end up with some very strange results.

1: #define MUL_IT(a, b) a * b        /* Wrong */
2: #define MUL_IT(a, b) (a * b)      /* Not enough */
3: #define MUL_IT(a, b) ((a) * (b))  /* Correct */

What's the big difference you may ask? Well, look at this example:

result = MUL_IT(2 + 3, 4 * 5) / 5;

   Expanded this becomes:

1: result = 2 + 3 * 4 * 5 / 5;       // = 14, Wrong
2: result = (2 + 3 * 4 * 5) / 5      // = 12, Just as wrong
3: result = ((2 + 3) * (4 * 5)) / 5  // = 20, Correct!

Abuse of defines usually involves badly formulated macros, complicated macros used inside other macros (making the code almost impossible to understand) or humungous arrays or mappings in defines that are used often. The basic rule is to keep macros short and fairly simple. Do that and you'll never have any problems.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated by Ronny Wikh on July, 8 2003 using texi2html