Escaping a # symbol in a #define macro?

39,818

Solution 1

As far as I remember you cannot use another preprocessor directive in define.

Solution 2

It is possible to insert a hash token into the preprocessed token stream. You can do it as follows:

#define MACRO(hash, name) hash include name
MACRO(#,"hello")

—expands to:

# include "hello"

However, the standard explicitly rules out any further analysis of such line for the existence of preprocessing directives [cpp.rescan]:

The resulting completely macro-replaced preprocessing token sequence is not processed as a preprocessing directive even if it resembles one.

Solution 3

The problem isn't actually getting a # symbol in the output of your preprocessor.

Apparently you want the preprocessor to reparse your file, to deal with newly created #include directives as part of macro expansion. It doesn't work that way. If a line starts with #, it's an instruction for the preprocessor and interpreted. If a line doesn't start with #, it's only subject to preprocessor transformation including macro substitution. This is a once-per-line test.

MACRO(Test)

does not start with #. Therefore it is not interpreted as a preprocessor directive; instead it's subject to macro replacement rules.

Solution 4

This is because the # has special meaning when used in a macro.

#  means quote the following token (which should be a macro parameter name)
## means concatenate the preceding and following tokens.

In your situation the # is not followed by a proper token. So in your situation we need to go through a level of indirection:

#define     QUOTE(name)     #name
#define     TEST(name)      QUOTE(name ## foo)

#include TEST(scot)

Solution 5

You can't do that. Preprocessor directives are recognized before macro expansion; if the macro expands into something that looks like a preprocessor directive, that directive will not be recognized. The best you can do is create a macro for the file name:

#define MACRO(name) "name##foo"
...
#include MACRO(Test)
Share:
39,818
Rob
Author by

Rob

C++, MFC, Win32, WTL, STL, Boost, HTML, CSS, JavaScript, Qt, Python, jQuery Mobile.

Updated on July 09, 2022

Comments

  • Rob
    Rob almost 2 years

    Without going into the gory details I want to use a #define macro that will expand to a #include but the '#' sign is confusing the preprocessor (as it thinks I want to quote an argument.)

    For example, I want to do something like this:

    #define MACRO(name) #include "name##foo"
    

    And use it thus:

    MACRO(Test)
    

    Which will expand to:

    #include "Testfoo"
    

    The humble # sign is causing the preprocessor to barf. MinGW gives me the following error:

    '#' is not followed by a macro parameter

    I guess I need to escape the # sign but I don't if this is even possible.

    Yes, macros are indeed evil...

  • EFraim
    EFraim almost 15 years
    Use <> instead of "". "" Are not interpolated.
  • polyglot
    polyglot almost 15 years
    Clearest answer on here I think - effectively he's asking for a 2nd parse of the preprocessor, well noted.
  • Rob
    Rob almost 15 years
    Thanks. I found a better way to achieve what I was after in the end, without using macros.
  • pbean
    pbean over 14 years
    It would have been nice if you mentioned in which way you achieved what you wanted? :-)
  • Marius
    Marius over 14 years
    that will not allow for the case when you want to replace it with two #includes, or perhaps eliminate them altogether. But it's perhaps the best option.
  • Jonathan Leffler
    Jonathan Leffler over 9 years
    But the output of this is not a #include directive (it is just a line that contains #include); you can't generate preprocessor directives like that. You also haven't really explained what BOOST_PP_CAT is and where you get it from.
  • Jonathan Leffler
    Jonathan Leffler over 9 years
    Note that a modern preprocessor won't expand the name inside the quotes; this will end up as #include "name##foo" regardless of the value passed to the macro.
  • Jonathan Leffler
    Jonathan Leffler over 9 years
    This works for the question, where the name to be included doesn't need .h appended. It is harder to make it work in a scenario where you have #include USR_HEADER(name) in the code, and you want it to become #include "name.h" for C or #include "cname" for C++. That's because token pasting doesn't work when one of the tokens is .h and because string concatenation occurs after the preprocessor is finished (so generating #include "name" ".h" leaves you with an invalid preprocessor directive). I'm not yet sure how to solve that, or STD_HEADER(stdio) for <stdio.h> or <cstdio>.
  • xryl669
    xryl669 about 8 years
    You can use also #define MACRO(name) #name "foo" that simply rely on string concatenation done when 2 strings are following on a single statement.
  • masterxilo
    masterxilo over 7 years
    @JonathanLeffler To be fair, if you google BOOST_PP_CAT you find only information on the macro that he meant. And the name is long enough to consider this a GUID ;)
  • Jonathan Leffler
    Jonathan Leffler over 7 years
    @xryl669: Note that adjacent string literal concatenation is done in Phase 6 of the translation process, but the preprocessor finishes in Phase 4. Thus, the #define MACRO(name) #name "foo" won't help; it will generate two separate strings which is not a valid header name.
  • Jonathan Leffler
    Jonathan Leffler over 7 years
    This answer doesn't seem to be related to the question, which is really asking about how to generate a file name for use with #include.