[comp.lang.c] Macro Substitution too Complex?

c60c-2ca@WEB.berkeley.edu (Andrew Choi) (05/05/90)

Hi everyone.  I thought I understood how macro substituion
works, until I came up with the following example:

Suppose that I have defined the following macros:


#define IMPLEMENT(C, T)		C ## _IMPLEMENTATION(T)

#define Apple_IMPLEMENTATION(T)				\
	implement T ## Apple	

#define Orange_IMPLEMENTATION(T)			\
	IMPLEMENT(Apple, T)				\
	Apple_IMPLEMENTATION(T)				\
	implement T ## Orange	

/* 1st invocation */
IMPLEMENT(Orange, int)

/* 2nd invocation */
Orange_IMPLEMENTATION(int)

And the results are (after some doctoring)

/* 1st invocation */
IMPLEMENT(Apple,  int)
implement  intApple
implement  intOrange	 

/* 2nd invocation */
implement  intApple
implement intApple
implement intOrange	

As you see, in the first instance, IMPLEMENT(Apple, int) is not
expanded, while in the second instance, it is expanded.  At
first I thought there may be a level on macro substitution, so I
defined also the following macros:

#define DECLARE(C, T)		C ## _DECLARATION(T)

#define Apple_DECLARATION(T)				\
	declare  T ## Apple	

#define Banana_IMPLEMENTATION(T)			\
	DECLARE(Apple, T)				\
	Apple_DECLARATION(T)				\
	implement T ## banana

/* 3rd invocation */
IMPLEMENT(Banana, float)

/* 4th invocation */
Banana_IMPLEMENTATION(float)

And the result is (again, after some doctoring):

/* 3rd invocation */
declare    floatApple
declare   floatApple
implement  floatbanana  

/* 4th invocation */
declare    floatApple
declare   floatApple
implement  floatbanana

Now this confuses me.  They are both the same.  If it has something
to do with level, inside the 3rd invocation, the first line should
have read DECLARE(Apple, float) instead.  Apparently, this has
nothing to do with the depth of macro substitution.

One possible explanation is that macro substitution is not recursive.
However, is this a standard behavior?  Does anyone know the "standard"
rules for performing macro substitution?  Is there a "standard"?

Any help or suggestion is GREATLY appreciated.




Andrew Choi
Internet Address:  c60c-2ca@web.berkeley.edu
Standard Disclaimer

karl@haddock.ima.isc.com (Karl Heuer) (05/06/90)

In article <1990May5.014816.26452@agate.berkeley.edu> c60c-2ca@WEB.berkeley.edu (Andrew Choi) writes:
>Hi everyone.  I thought I understood how macro substituion
>works, until I came up with the following example: ...

Since the example uses the `##' operator, we're talking about ANSI C here.

>One possible explanation is that macro substitution is not recursive.

You got it.  It's normally pretty useless for macro substitution to be done
recursively, since there's no way for it to bottom out (the preprocessor
sublanguage lacks a conditional that can be executed within a macro), so it
was decreed to be nonrecursive (so one can write `#define char signed char',
for example).

>However, is this a standard behavior?

Yes, this sort of behavior is required for a conforming implementation.

>Does anyone know the "standard" rules for performing macro substitution?

I would guess that very few people know them completely; I'm not one of them.
There are some rather subtle issues involved; see the examples in the ANS.

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint