Mouin
Mouin

Reputation: 1103

Number of arguments in macro

I am writing a "mapping macro" and want to use it to generate enums, classes, function calls ...

This is how the macro looks like:

#define MY_MAPPING(ENTRY)                                   \
ENTRY(a,                    {0x10,0x01,0x01,0x00}, foo) \
ENTRY(b,                    {0x10,0x01,0x02,0x00}, boo)

Now I am trying to generate an enumeration using the "mapping macro"

#define STRCONC(a,b) a##b
#define EXPAND_TO_ENUM(a,b,c) STRCONC(a,_Idx),

typedef enum
{
    MY_MAPPING(EXPAND_TO_ENUM)
}example_Enum;

I am getting the error: macro "EXPAND_TO_ENUM" passed 6 arguments, but takes just 3. The reason is the elements between brackets, the compiler is considering each element into the bracket as a single element Why and do you have any Idea to solve the problem?

Of course using parentheses will solve the problem but I don't want to use them since I need to use the elements between brackets as function arguments after for foo and boo, they are accepting array as input.

Upvotes: 1

Views: 86

Answers (1)

H Walters
H Walters

Reputation: 2674

I am getting the error: macro "EXPAND_TO_ENUM" passed 6 arguments, but takes just 3. The reason is the elements between brackets, the compiler is considering each element into the bracket as a single element Why

Macros are processed by the preprocessor, not the "language proper". A function-like macro invocation recognizes string-boundaries and will match parentheses, but not braces or square brackets... to the preprocessor, [, {, }, and ] are just tokens having nothing to do with each other. (Incidentally, the name for the thing you're writing is an X-macro).

When you invoke MY_MAPPING(something), assuming that something "expands" to a token that's #define'd as a function-like macro, then once this part is evaluated:

  ENTRY(a, {0x10,0x01,0x01,0x00}, foo)

...it will be a macro invocation with six arguments:

  • a
  • {0x10
  • 0x01
  • 0x01
  • 0x00}
  • foo
do you have any Idea to solve the problem?

Part 1 of the solution: Use parentheses. If you use parentheses (the preprocessor does match those):

  ENTRY(a, (0x10, 0x01, 0x01, 0x00), foo)

...then your invocation has three arguments:

  • a
  • (0x10, 0x01, 0x10, 0x00)
  • foo

Part 2 is implied:

they are accepting array as input.

...but I can't figure out what you're really saying here, other than that somehow you want that argument 2 to be surrounded by braces. That you can do easily enough:

#define MY_MAPPING(ENTRY)                               \
ENTRY(a,                    (0x10,0x01,0x01,0x00), foo) \
ENTRY(b,                    (0x10,0x01,0x02,0x00), boo)
#define BRACIFY(...) { __VA_ARGS__ }
#define MAKE_SOME_INT_ARRAY_THINGY(ID, INIT, X) int ID[] = BRACIFY INIT;
MY_MAPPING(MAKE_SOME_INT_ARRAY_THINGY)

...expands to:

int a[] = { 0x10,0x01,0x01,0x00 }; int b[] = { 0x10,0x01,0x02,0x00 };

Upvotes: 2

Related Questions