1
votes

I'm trying to do something using C preprocessor. I have this macros:

#define _MAX(x, y) (((x)) > ((y))) ? (x) : (y))

#define MAX1 _MAX(1,
#define MAX2 _MAX(2,0))

#define RIGHT _MAX(1,_MAX(2,0))
#define WRONG MAX1 MAX2

In this case, RIGHT gives me the right expression but WRONG, even though it's the same, expands the macro to blank.

It seems to me that's because after expanding MAX1 to _MAX(1, it detects there is a _MAX macro to expand and tries to do it without expanding the MAX2, which haves the other half of the statement.

If I'm right, is there any way that I can delay the _MAX macro expansion until MAX2 it's expanded?

2
Just a stab in the dark, have you tried defining MAX2 before MAX1 ? - Neil
Note: Adding double parentheses doesn't make the expresssion more secure ;) - Karoly Horvath
@Neil that didn't work but even if it did I probably couldn't use it in my case, which is a little more complex then that - rnunes
With gcc I get error: unterminated argument list invoking macro "_MAX" - Karoly Horvath
I hear inline functions are really nice. - Lundin

2 Answers

3
votes

It's correct, because of the order WRONG is being expanded. First it expands the macro to

MAX1 MAX2

then it rescans that to expand it further, first it expands MAX1 to _MAX(1, and it's when rescanning this the error occurs as it doesn't find the termination of the argument list.

If you had defined WRONG as MAX1 MAX2 ) it would have expanded it without complaints (but not with the same expansion of course).

3
votes

C preprocessor scans for macros after each expansion. Section 6.10.3.4 states:

After all parameters in the replacement list have been substituted and # and ## processing has taken place, all placemarker preprocessing tokens are removed. Then, the resulting preprocessing token sequence is rescanned, along with all subsequent preprocessing tokens of the source file, for more macro names to replace.

One way to force C preprocessor to expand macro B ahead of macro A is to pass B to A as a parameter:

#define _MAX(x, y) (((x)>(y))?(x):(y))

#define MAX1(Y) _MAX(1,Y)
#define MAX2 _MAX(2,0)

#define NEW_RIGHT MAX1(MAX2)

Now MAX2 becomes an argument to MAX1, so its content is expanded in the process of expanding MAX1.

Demo.