[comp.lang.c] Question on ANSI ## pre-processor operator.

knurlin@spf.trw.com (Scott Karlin) (05/15/91)

I am looking for a clarification on the ANSI-C token merging
operator (##).  According to H&S:  "After *all* [emphasis mine]
macro replacements have been done, the two tokens surrounding
any ## operator are combined into a single token."  I interpret
this to mean that:

#define INDEX 0
#define FN_NAME(x) name ## x
void FN_NAME(INDEX) () { printf("Hello\n"); }

Should expand to:

void name ## 0 () { printf("Hello\n"); }

And then:

void name0 () { printf("Hello\n"); }

Which is what I want.  However, two different ANSI (they say) compilers
are not defining a function called "name0".  Here is the actual code I
used:

/*
**   example.c
*/

#include <stdio.h>

#define PID 0

/*
**   Token merging macro...
*/
#define FN_NAME(x)  funct ## x

/*
**   Function prototypes...
*/
void main(void);
void funct0(void);


/*
**   Simple main function.  Nothing tricky here...
*/

void main()
{
   funct0();
   return;
}


/*
**   I believe that this should get expanded by the pre-processor to
**   funct0 ()   Note that I have intentionally placed a space between
**   the macro "call" and the empty function parameter list.
*/

void FN_NAME(PID) ()
{
   printf("Hello, world.\n");
   return;
}

Any information on the correct interpretation would be most welcome.

-- Scott Karlin                    Internet:  knurlin@spf.trw.com
-- TRW Data Systems Center         UUCP:      ...!uunet!knurlin@spf.trw.com
-- One Space Park, O2-1761         Phone: (213) 812-7335
-- Redondo Beach, CA 90278-1071    FAX:   (213) 812-8800

vinoski@apollo.HP.COM (Stephen Vinoski) (05/15/91)

In article <28302040.69ED@deneva.sdd.trw.com> knurlin@spf.trw.com (Scott Karlin) writes:
>I am looking for a clarification on the ANSI-C token merging
>operator (##).  According to H&S:  "After *all* [emphasis mine]
>macro replacements have been done, the two tokens surrounding
>any ## operator are combined into a single token."  I interpret
>this to mean that:
>
>#define INDEX 0
>#define FN_NAME(x) name ## x
>void FN_NAME(INDEX) () { printf("Hello\n"); }

(I have cross-posted this to comp.std.c since a similar question
recently came up there.  Follow-ups have been directed to
comp.lang.c.)

I had a problem with token pasting similar to yours.  A compiler
writer said that the problem was caused by the fact that I was
attempting to paste arbitrary text with macro parameters; he said that
token pasting is only meant to work on macro parameters.

The ANSI C standard appears to agree with him; I believe it is section
3.8.3.3 (I don't have the standard handy) that says that ## causes
macro parameters to be pasted together.  If I have misinterpreted the
standard, I'm sure I will hear about it.  :-)

I have also noticed that K&R II only shows macro parameters being
pasted together.

What if you change your example to:

#define INDEX 0
#define REAL_FN_NAME(x,y) x ## y
#define FN_NAME(x)        REAL_FN_NAME(name,x)

Then your example usage:

>void FN_NAME(INDEX) () { printf("Hello\n"); }

should produce the desired result.


-steve

| Steve Vinoski  (508)256-0176 x5904       | Internet: vinoski@apollo.hp.com  |
| HP Apollo Division, Chelmsford, MA 01824 | UUCP: ...!apollo!vinoski         |

steve@taumet.com (Stephen Clamage) (05/15/91)

knurlin@spf.trw.com (Scott Karlin) writes:

>I am looking for a clarification on the ANSI-C token merging
>operator (##).  According to H&S:  "After *all* [emphasis mine]
>macro replacements have been done, the two tokens surrounding
>any ## operator are combined into a single token."  I interpret
>this to mean that:

>#define INDEX 0
>#define FN_NAME(x) name ## x
>void FN_NAME(INDEX) () { printf("Hello\n"); }

>Should expand to:

>void name ## 0 () { printf("Hello\n"); }

>And then:

>void name0 () { printf("Hello\n"); }

Not quite.  Let's review.  In the absence of any # or ## tokens in a
macro replacement string, each macro parameter appearing in the
replacement string is replaced by its fully-macro-expanded actual
argument.  Example
	#define INDEX 0
	#define FN(x) fn x
	FN(INDEX)
becomes
	fn 0
because the actual argument INDEX is fully expanded before it replaces
the formal parameter x.

When a macro parameter in the replacement string is preceded by # or
preceded or followed by ##, the rule is different.  The actual argument
replaces the formal argument without any expansion, the # or ## operator
is applied, then the resulting text is rescanned.  This allows you to
build up macro names for further replacement.
Example:
	#define INDEX 0
	#define FN(x) fn ## x
	FN(INDEX)
becomes
	fn ## INDEX
which becomes
	fnINDEX
which cannot be further expanded.

Your example will not work with the extra level of macro replacement.
It can be used like this:
	#define FN_NAME(x) name ## x
	void FN_NAME(0) () { printf("Hello\n"); }
which yields
	void name0 () { printf("Hello\n"); }
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

vinoski@apollo.HP.COM (Stephen Vinoski) (05/16/91)

In article <519416cd.20b6d@apollo.HP.COM> vinoski@apollo.HP.COM (Stephen Vinoski) writes:
>In article <28302040.69ED@deneva.sdd.trw.com> knurlin@spf.trw.com (Scott Karlin) writes:
>>I am looking for a clarification on the ANSI-C token merging
>>operator (##).  According to H&S:  "After *all* [emphasis mine]
>>macro replacements have been done, the two tokens surrounding
>>any ## operator are combined into a single token."  I interpret
>>this to mean that:
>>
>>#define INDEX 0
>>#define FN_NAME(x) name ## x
>>void FN_NAME(INDEX) () { printf("Hello\n"); }
>
>I had a problem with token pasting similar to yours.  A compiler
>writer said that the problem was caused by the fact that I was
>attempting to paste arbitrary text with macro parameters; he said that
>token pasting is only meant to work on macro parameters.
>
>The ANSI C standard appears to agree with him; I believe it is section
>3.8.3.3 (I don't have the standard handy) that says that ## causes
>macro parameters to be pasted together.  If I have misinterpreted the
>standard, I'm sure I will hear about it.  :-)

Well, what do you know - I *did* misinterpret the standard.  Sigh.
Section 3.8.3.3 states that preprocessor tokens can be pasted
together.  The problem knurlin@spf.trw.com has is caused by the fact
that token pasting occurs before the result is rescanned for further
macro replacement.  Thanks to steven@pacific.csl.uiuc.edu (Steven
Parkes) for setting me straight on this one.

I hereby promise not to quote the standard from memory again.


-steve

| Steve Vinoski  (508)256-0176 x5904       | Internet: vinoski@apollo.hp.com  |
| HP Apollo Division, Chelmsford, MA 01824 | UUCP: ...!apollo!vinoski         |