sg1
sg1

Reputation: 485

C/C++ preprocessing ambiguity

On executing the following code using 'Macro Definitions Set 1', I encounter the error "C2065: 'C1' : undeclared identifier".

While using 'Macro Definitions Set 2', the code runs to give an output of 2.

I am guessing it has something to do with preprocessor tokenization. Please Explain.

#include <iostream>

// Macro Definitions Set 1
#define A       1
#define D(n)    B(n)
#define B(n)    C##n
#define CA      2

// Macro Definitions Set 2
//#define A     1
//#define D(n)  C##n
//#define CA        2

int main ()
{

    printf ("%d", D(A));
}

Upvotes: 2

Views: 419

Answers (3)

caf
caf

Reputation: 239011

With your first set of macros:

#define A       1
#define D(n)    B(n)
#define B(n)    C##n
#define CA      2

D(A) is evaluated by performing macro replacement on A and then substituting it into the replacement list for D(n). The macro replacement results in 1, so this gives B(1). B(1) is then recursively evaluated, giving C##1 which is concatenated to the preprocessing token C1.

With your second set of macros:

#define A     1
#define D(n)  C##n
#define CA    2

When D(A) is evaluated, macro replacement on the argument n is not performed, because it is prefixed by ##. This gives C##A, which results in the preprocessing token CA. This is then re-examined for macros to replace, which results in 2.

Upvotes: 2

fefe
fefe

Reputation: 3432

The macro parameter is substituted unless it is before or after ##, or after #.

So in Set 1, D(A) becomes B(1) after substitution of D(n), which is substituted to C1 after rescan.

In Set 2, D(A) becomes CA, where A is not substituted as it is after ##, and CA becomes 2 after rescan.

Upvotes: 3

ssube
ssube

Reputation: 48247

You need to go through each stage during the resolution. Basically, the preprocessor does an iterative search and replace until it runs out of tokens (it can be more complex, but for current purposes, that's what happens). It goes left to right on each line.

Now, what happens using set 2:

  • printf("%d", D(A)); <- first preprocessor token found is D(A), so:
  • printf("%d", CA);
  • printf("%d", 2);

What appears to be happening with set 1:

  • printf("%d", D(A)); <- first preprocessor token found is D(A), so:
  • printf("%d", B(A)); <- now, the next token found is A
  • printf("%d", B(1));
  • printf("%d", C1); <- and error

The issue is that the replacement occurs, then the preprocessor finds the A next (perhaps not restarting the line) and performs another replacement. Then it does go over it again, but finds B(1).

To test this, you can just leave off some of the later declarations and preprocess to a file. That will show you exactly what's happening.

Upvotes: 0

Related Questions