Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.compilers > #1870 > unrolled thread

Preprocessing ##

Started byHans-Peter Diettrich <DrDiettrich1@netscape.net>
First post2017-05-13 08:49 +0200
Last post2017-06-02 08:04 +0200
Articles 5 — 4 participants

Back to article view | Back to comp.compilers


Contents

  Preprocessing ## Hans-Peter Diettrich <DrDiettrich1@netscape.net> - 2017-05-13 08:49 +0200
    Re: Preprocessing ## Hans-Peter Diettrich <DrDiettrich1@netscape.net> - 2017-05-15 11:28 +0200
    Re: Preprocessing ## Kaz Kylheku <686-678-9105@kylheku.com> - 2017-05-15 13:41 +0000
    Re: Preprocessing ## George Neuner <gneuner2@comcast.net> - 2017-05-15 11:31 -0400
      Re: Preprocessing ## Hans-Peter Diettrich <DrDiettrich1@aol.com.dmarc.email> - 2017-06-02 08:04 +0200

#1870 — Preprocessing ##

FromHans-Peter Diettrich <DrDiettrich1@netscape.net>
Date2017-05-13 08:49 +0200
SubjectPreprocessing ##
Message-ID<17-05-003@comp.compilers>
How is the C preprocessor assumed to handle the ## concatenation operator?

In the Windows headers I found macros like
   #define foo(x) bar(##baz(x))
where an expansion into ... (baz ... doesn't make sense, because "(baz"
is not a valid preprocessor token. Can somebody explain the meaning and
handling of such constructs?

DoDi [I would guess that some macro between ( and ## expanded to
nothing.  Or it could just be one of those text editing errors. -John]

[toc] | [next] | [standalone]


#1871

FromHans-Peter Diettrich <DrDiettrich1@netscape.net>
Date2017-05-15 11:28 +0200
Message-ID<17-05-004@comp.compilers>
In reply to#1870
Am 13.05.2017 um 08:49 schrieb Hans-Peter Diettrich:
> How is the C preprocessor assumed to handle the ## concatenation operator?
>
> In the Windows headers I found macros like
>   #define foo(x) bar(##baz(x))
> where an expansion into ... (baz ... doesn't make sense, because "(baz"
> is not a valid preprocessor token. Can somebody explain the meaning and
> handling of such constructs?

[John]
> [I would guess that some macro between ( and ## expanded to
> nothing.

The #define's leave no room for macros to the left of ##.

If, in above example, bar() were another macro, would the ## operator
stay literal part of the argument's token sequence?

E.g. with
   #define bar(z) some_prefix z
would foo(suffix) expand into
   some_prefix ##baz(suffix)
?

> Or it could just be one of those text editing errors. -John]

Not here. A comment before a couple of such #define's suggests, that
they are a workaround for the lack of variadic macros ("..." arguments).

DoDi

[toc] | [prev] | [next] | [standalone]


#1872

FromKaz Kylheku <686-678-9105@kylheku.com>
Date2017-05-15 13:41 +0000
Message-ID<17-05-005@comp.compilers>
In reply to#1870
On 2017-05-13, Hans-Peter Diettrich <DrDiettrich1@netscape.net> wrote:
> How is the C preprocessor assumed to handle the ## concatenation operator?
>
> In the Windows headers I found macros like
>    #define foo(x) bar(##baz(x))
> where an expansion into ... (baz ... doesn't make sense, because "(baz"
> is not a valid preprocessor token. Can somebody explain the meaning and
> handling of such constructs?

According to ISO C, if the result of the ## operator is an invalid
token, the behavior is undefined.

If you're making a compiler which will have to handle the unmodified
header files from Microsoft platform development kits for Windows, you
have little choice but to implement compatible preprocessing, which
handles whatever constructs occur, in the same way.

In other words, the actual meaning here is "whatever Visual C does".
[Ugh.  But I have to agree. -John]

[toc] | [prev] | [next] | [standalone]


#1873

FromGeorge Neuner <gneuner2@comcast.net>
Date2017-05-15 11:31 -0400
Message-ID<17-05-006@comp.compilers>
In reply to#1870
On Sat, 13 May 2017 08:49:36 +0200, Hans-Peter Diettrich
<DrDiettrich1@netscape.net> wrote:

>How is the C preprocessor assumed to handle the ## concatenation operator?

It concatenate tokens *prior* to expansion.  If the token references a
parameter of the current macro, the (text of the) parameter is
substituted, otherwise the token is simply copied.

e.g, #define foo(x)  one ## two
     ... foo(help) =>  onetwo

     #define foo(x)  x ## _me
     ... foo(help) => help_me


>In the Windows headers I found macros like
>   #define foo(x) bar(##baz(x))
>where an expansion into ... (baz ... doesn't make sense, because "(baz"
>is not a valid preprocessor token. Can somebody explain the meaning and
>handling of such constructs?
>
>DoDi
>[I would guess that some macro between ( and ## expanded to
>nothing.  Or it could just be one of those text editing errors. -John]

I think John probably is correct that you've found typos.  If it were
the result of a macro substitution, you would see it only in the
output of the preprocessor - it would not be visible in an input
header file.

Moreover, although I'm not 100% certain, I believe the preprocessor
does not substitute inside (it's own) preprocessor definitions, but
rather only substitutes into C code.

George

[toc] | [prev] | [next] | [standalone]


#1884

FromHans-Peter Diettrich <DrDiettrich1@aol.com.dmarc.email>
Date2017-06-02 08:04 +0200
Message-ID<17-06-003@comp.compilers>
In reply to#1873
Am 15.05.2017 um 17:31 schrieb George Neuner:
> On Sat, 13 May 2017 08:49:36 +0200, Hans-Peter Diettrich
> <DrDiettrich1@netscape.net> wrote:
>
>> How is the C preprocessor assumed to handle the ## concatenation operator?
>
> It concatenate tokens *prior* to expansion.  If the token references a
> parameter of the current macro, the (text of the) parameter is
> substituted, otherwise the token is simply copied.

In a newer draft I found the constraint, that ## is an operator only if
present in the replacement list (macro body), not from an argument.

>> In the Windows headers I found macros like
>>   #define foo(x) bar(##baz(x))

Here the constraint is violated, ## is part of the argument and thus not
recognized as a preprocessor operator.


>> [I would guess that some macro between ( and ## expanded to
>> nothing.  Or it could just be one of those text editing errors. -John]
>
> I think John probably is correct that you've found typos.  If it were
> the result of a macro substitution, you would see it only in the
> output of the preprocessor - it would not be visible in an input
> header file.

In the meantime I guess that this construct is a creative use of the
preprocessor, when *also* used for some other postprocessor. The C
compiler may never see the ## if bar(x) has an empty definition, with
the argument unused. This seems to be the case with above example,
unless a project or tool adds global definitions which result in a
different definition of bar(x).

The standard also includes an example
   #define hash_hash # ## #
which expands into a new ## token, which *is not* the ## operator. This
may or may not mean that ## is recognized and handled as a preprocessor
operator *only if* it occurs in the replacement list (body) of a macro
definition. Such a token is not accepted subsequently by a C compiler,
but may be recognized by some other tool. Likewise the standard requires
that a # operator must be followed by a macro argument, else it is not
recognized as a preprocessor operator. This signals to me that the
preprocessor is allowed to output token sequences which are not valid C
code, but may be valid when processed by some other tool.


> Moreover, although I'm not 100% certain, I believe the preprocessor
> does not substitute inside (it's own) preprocessor definitions, but
> rather only substitutes into C code.

Right, immediate evaluation of # ## #, as a constant expression during
macro definition, would result in a new ## token inside the replacement
list, which would be recognized as another ## operator during a
subsequent macro expansion. This were not the behaviour indicated by the
description of above example.

Thanks for your comments, without which I e.g. had guessed that constant
expression evaluation were allowed during macro definition.

DoDi

[toc] | [prev] | [standalone]


Back to top | Article view | comp.compilers


csiph-web