45

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...

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
Rob
  • 76,700
  • 56
  • 158
  • 197

8 Answers8

41

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.

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
32

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.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 7
    Clearest answer on here I think - effectively he's asking for a 2nd parse of the preprocessor, well noted. – polyglot Jul 16 '09 at 11:50
31

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

EFraim
  • 12,811
  • 4
  • 46
  • 62
  • 1
    Thanks. I found a better way to achieve what I was after in the end, without using macros. – Rob Jul 16 '09 at 19:07
  • 58
    It would have been nice if you mentioned in which way you achieved what you wanted? :-) – pbean Dec 04 '09 at 13:16
12

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)
Shahbaz
  • 46,337
  • 19
  • 116
  • 182
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • 2
    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 `` or ``. – Jonathan Leffler Dec 27 '14 at 20:57
7

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)
John Bode
  • 119,563
  • 19
  • 122
  • 198
  • 2
    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 Dec 27 '14 at 08:57
  • 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. – xryl669 Apr 14 '16 at 13:16
  • @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 Nov 30 '16 at 19:12
2

This might work (it works for regular #define macros with no parameters, but I haven't tested it with macros with parameters).

#define MACRO(name) <name##foo>
#include MACRO(Test)
Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
  • 1
    Use `<>` instead of `""`. `""` Are not interpolated. – EFraim Jul 16 '09 at 06:56
  • 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. – Marius Dec 11 '09 at 18:37
1
#define HASH_SIGN #
BOOST_PP_CAT(HASH_SIGN, include)
David F.
  • 27
  • 2
  • 4
    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 Dec 27 '14 at 08:54
  • 1
    @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 ;) – masterxilo Nov 30 '16 at 18:59
0
#define PARAM_NAME Param
#define GETNAME_(a) #a
#define GETNAME(a) GETNAME_(a)

int Param;
printf("%s = %i\n", GETNAME(PARAM_NAME), PARAM_NAME);
  • 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`. – Jonathan Leffler Nov 30 '16 at 19:18