Maxim Veksler
Maxim Veksler

Reputation: 30232

Macro expansion in C

This macro

#define f(x) x x
     f (1
     #undef f
     #define f 2
     f)

Expands to this 1 2 1 2 according to this link.

It actually does this, I’ve verified with Xcode Product > Perform Action > Preprocess but what steps does the preprocessor follow while expanding this macro?

Upvotes: 4

Views: 611

Answers (2)

Étienne
Étienne

Reputation: 5023

Initial situation:

f (1
#undef f
#define f 2
f)

If we refer to the link you provided, the macro is preprocessed in 2 steps:

Step 1: argument pre-expansion

If, within a macro invocation, that macro is redefined, then the new definition takes effect in time for argument pre-expansion

Replacement of f, used as argument to the function-like macro, by 2:

f(1 f) -> f (1 2)

Step 2: argument replacement

but the original definition is still used for argument replacement

Resolution of the function-like macro f using its original definition:

f(1 2) -> 1 2 1 2



The whole thing is actually equivalent to the following:

#define f(x) x x  
#define g 2
f(1 g)

Upvotes: 3

Maxim Veksler
Maxim Veksler

Reputation: 30232

I think that what happens is as following, to be able to better visualize the steps let’s rewrite the #define statement by adding distinguishing parentheses.

Step 0

#define f(x) (x) [x]

f (1
#undef f
#define f 2
f)

// Note, this does not produce a valid C code. I’m playing with it to understand the actions taken by the preprocess, not to get it compiled. View the results of the preprocessor via Product > Action > Preprocess as I’ve shown above.

So, first step taken by the preprocessor is substitution, x is being replaced by the value provided in the statement (this case, “1”), there are 2 times x in the macro values, so the same substitution happens twice. The (), and [] brackets are here to help distinguish between the 2 paths:

Step 1

(1
#undef f
#define f 2
f) [1
    #undef f
    #define f 2
    f]

Then #undef the macro f, which does exist and redefine it as f 2

Step 2

(1 f) [1 f]

At the final step preform a simple substitution of f with the value it is currently carrying, which is in this case 2

Step 3

(1 2) [1 2]

That’s it. The expected result 1 2 1 2 has been substituted to the ground.

Upvotes: 0

Related Questions