[comp.lang.c] How SHOULD these macros work?

schweitz@lexvmc.iinus1.ibm.com ("Eric Schweitz") (02/16/91)

From: schweitz@lexvmc.iinus1.ibm.com
Date: 15 February 1991, 10:41:22 EST

I have a question concerning the preprocessor. Namely, what behavior
SHOULD be expected from the following:

#define one val1,val2
#define two(arg1,arg2)  arg1+arg2
....
   two (one)  // ?

Should this evaluate to:

a) val1+val2
  -or-
b) val1,val2+

Please excuse me if this is a neophyte question.
Also, is this behavior different of the same for C and C++?

Thanks,
Schweitz        schweitz@lexvmc.iinus1.ibm.com

crawford@scri.fsu.edu (Lee Crawford) (02/17/91)

Well, its a simple consideration of the preprocessors replacement ordering.

You asked:

|  What behavior SHOULD be expected from the following:
|
|  #define one val1,val2
|  #define two(arg1,arg2) arg1+arg2
|
|   ....
|
|     two(one)

I guess I'll give answering your question a shot:

  I think what you have to understand is how the C/C++ preprocessor works, 
for it is the preprocessing phase of compilation that is causing the effects
that
you find strange.

  The initial actions of the preprocessor are to break up the text of any
source
code into a stream of tokens. As it breaks off these tokens it scans then for 
macro calls. (A macro constant just has not parrenthesization) Thus, for either
of
the following two code segments:

  #define one val1,val2
  #define two(arg1,arg2) arg1+arg2

or

  #define two(arg1,arg2) arg1+arg2
  #define on val1,val2.

You notice that the first recognized token of the program text:

  two(one)

would be the string "two". Thus regardless of the ordering of the definitions
or
whatnot, the preprocesser first turns its attentions to a replacement of the
macro "two". Thus:

  two(one)

becomes

   one+

and you will likely find yourself with an error message mentioning that the 
required number of arguments was not present. When macro replacement occurs
during preprocessing, after a single replacement the preprocessor resumes token
scanning at the beginning of the previous expansion. Thus the preprocessor is 
now trying to figure out what to do with:

  one+

It then finds the token "one" and replaces it with "val1,val2". And

  one+

becomes

  val1,val2+.  

I hope this has all made sense. If you wanted val1+val2 as the expansion of 
your macro invocation then you will have to sort out a different way of doing
so.

-------------------- Cut here ---------------------------------------

  Lee Crawford
  Florida State University 
  Department of Physics
  crawford@fsulcd.physics.fsu.edu (INTER/ARPA-NET)
  fsulcd::crawford (DECnet)
  (904) 644 2334 (LipNET)

-------------------------------------------------------------------

zvs@bby.oz.au (Zev Sero) (02/19/91)

Eric = schweitz@lexvmc.iinus1.ibm.com ("Eric Schweitz")

Eric> I have a question concerning the preprocessor. Namely, what behavior
Eric> SHOULD be expected from the following:

Eric> #define one val1,val2
Eric> #define two(arg1,arg2)  arg1+arg2
Eric> ....
Eric>    two (one)  // ?

Eric> Should this evaluate to:

Eric> a) val1+val2
Eric>   -or-
Eric> b) val1,val2+

The correct answer is b.  I quote from H&S 2, page 33:

  Once a macro call has been expanded, the scan for macro calls
  resumes at the beginning of the expansion; this is so that names of
  macros may be recognized within the expansion for the purpose of
  further macro replacement...Macro replacement is also not performed
  within the actual argument token strings of a complex macro call at
  the time the macro call is being scanned. Macro names are recognised
  within actual argument token strings only during the rescanning of
  the expansion.

Therefore your macro is expanded in the following steps:
  two (one) -->  one+
At this point one is not recognised as a macro. Then the expression is
rescanned:
  one+ --> val1,val2+
--
	                                Zev Sero  -  zvs@bby.oz.au
This I say unto you, be not sexist pigs.
		-  The prophetess, Morgori Oestrydingh  (S.Tepper)