Go to the first, previous, next, last section, table of contents.

Self-Referential Macros

A self-referential macro is one whose name appears in its definition. A special feature of ANSI Standard C is that the self-reference is not considered a macro call. It is passed into the preprocessor output unchanged.

Let's consider an example:

#define foo (4 + foo)

where `foo' is also a variable in your program.

Following the ordinary rules, each reference to `foo' will expand into `(4 + foo)'; then this will be rescanned and will expand into `(4 + (4 + foo))'; and so on until it causes a fatal error (memory full) in the preprocessor.

However, the special rule about self-reference cuts this process short after one step, at `(4 + foo)'. Therefore, this macro definition has the possibly useful effect of causing the program to add 4 to the value of `foo' wherever `foo' is referred to.

In most cases, it is a bad idea to take advantage of this feature. A person reading the program who sees that `foo' is a variable will not expect that it is a macro as well. The reader will come across the identifier `foo' in the program and think its value should be that of the variable `foo', whereas in fact the value is four greater.

The special rule for self-reference applies also to indirect self-reference. This is the case where a macro x expands to use a macro `y', and the expansion of `y' refers to the macro `x'. The resulting reference to `x' comes indirectly from the expansion of `x', so it is a self-reference and is not further expanded. Thus, after

#define x (4 + y)
#define y (2 * x)

`x' would expand into `(4 + (2 * x))'. Clear?

But suppose `y' is used elsewhere, not from the definition of `x'. Then the use of `x' in the expansion of `y' is not a self-reference because `x' is not "in progress". So it does expand. However, the expansion of `x' contains a reference to `y', and that is an indirect self-reference now because `y' is "in progress". The result is that `y' expands to `(2 * (4 + y))'.

It is not clear that this behavior would ever be useful, but it is specified by the ANSI C standard, so you may need to understand it.


Go to the first, previous, next, last section, table of contents.