开发者

(Weird?) GCC Preprocessor Behaviour

I guess most of you who have worked with C/C++ have an intuition of how the preprocessor works (more or less). I thought so until today, but my intuition was proved wrong. Here is the story:

Today I tried something, but I can not explain the result. First consider the following code:

#define A B
#define B A

A
B

What happens? Well, the result after compiling it with the -E flag is this:

A
B

Well, ok, maybe not what anyone would expect, but it is explainable. I guess that the preprocessor somehow figured out that there is some problem, and did nothng.

The next thing I tried was this:

#define A B
#define B A C
#define C x

A
B

Now to the, for me, unexplainable result:

A x
B x

How did this happen? I can not figure out any reasonable way of how this happened. The first command (#define A B) can not be executed, because then A would be replaced by B, and开发者_开发知识库 the final result should be same for both. But if it is not, then there is no way that "A x" can happen!

My question: What am I missing? Obviously I don't know the exact way of how the preprocessor works. Do you know any sources about it?


Self-Referential Macros explains. Expansion is applied deeply but stops once a macro references itself.


#define A B
#define B A C
#define C x

A -> B -> A C -> A x 
B -> A C -> B x

Expansion is token by token "lazily"


Each chain of substitutions can visit any macro definition at most once. Among other things, this means that you can't have recursive macros.

The substitutions for your second example will look like this:

A --[evaluate A]--> B --[evaluate B]--> A C --[evaluate C]--> A x
B --[evaluate B]--> A C --[evaluate A,C]--> B x

During the last step of the first line, A is not evaluated because it was already invoked previously. Similarly, in the second line, evaluation stops at B because it has already been visited during the first step.

The relevant section of the C99 standard would be 6.10.3.4 Rescanning and further replacement.


Well, ok, maybe not what anyone would expect, but it is explainable. I guess that the preprocessor somehow figured out that there is some problem, and did nothng.

Nope. If the preprocessor does an expansion, it expands a symbol only once. So in your first example for the A: A gets's expanded to B, B expands to A and here the expansion stops. In the second line the B gets expanded to an A which expands to a B, where expansion stops, because we expanded B already.

If you apply logic to your second example, then the result becomes immediately obvious.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜