1

I am trying to understand the X-macros topic in detail. But didn't get the full clarity on this. It would be better if any one of the expert will explain this topic with some example "how to use, how to call."

I have found several articles, but didn't get the full clarity on this. In all places, they have used pieces of code where i am lacking in using of those X-macros.

Thanks in advance Partha

2 Answers2

2

Idea is that you redefine macro X to make data fit your current purpose.

You need at least 2 files. First is a huge table with necessary information, and others where data is used.

table.x:

X("Human",  2, HUMAN)
X("Spider", 8, SPIDER)

module.c:

// ID constants
enum {
#define X(description, legs, id) id,
#include "table.x"
#undef X
    COUNT   // Last element is total number of elements
};

// Leg array
int NumberOfLegs [] = {
#define X(description, legs, id) legs,
#include "table.x"
#undef X
};

// Description array
const char * Descriptions [] = {
#define X(description, legs, id) description,
#include "table.x"
#undef X
};

Preprocessed output would be:

// ID constants
enum {
    HUMAN,
    SPIDER,
    COUNT   // Last element is total number of elements
};

// Leg array
int NumberOfLegs [] = {
    2,
    8,
};

// Description array
const char * Descriptions [] = {
     "Human",
     "Spider",
};

In the above example it is easy to add new items to tables. If you managed those lists separately, it would be more easier to make an error.

Edit:

Some clarification on macro usage.

In first line #define X(description, legs, id) legs, we define X macro. Macro must have same number of arguments as our table.x has on each line. For this usage we are only interested on legs parameter. Note that argument names are meaningless, we could as well do #define X(a, b, c) b,.

Second line #include "table.x" includes contents of table.x to module.c. Because macro X has been defined, preprocessor does text replacement to each line with call to X.

Third line #undef X is only for convenience. We remove definition of X so it can be redifined later without compiler throwing warnings.

user694733
  • 13,861
  • 1
  • 40
  • 62
  • If you don't mine, can you explain the following code what you are using in the above example. #defineX(description, legs, id) legs, #include "table.x" #undef X – user1537070 Oct 25 '13 at 12:11
  • @user1537070 See my edit. – user694733 Oct 25 '13 at 12:51
  • @user694733 I don’t see the reason of using 2 files. May I know why you said to use at least 2 files? – noman pouigt Apr 12 '18 at 07:40
  • @nomanpouigt It can be done with one file only, as other answer shows. With 2 file method there is less problem with max line length, but that is not as big problem with modern compilers anymore. – user694733 Apr 13 '18 at 05:21
1

You basically #define a list of variables as parameters to an place holder macro X:

#define X_LIST_OF_VARS \
    X(my_first_var) \
    X(another_variable) \
    X(and_another_one)

You then use the template:

#define X(var) do something with var ...
X_LIST_OF_VARS
#undefine X

to make code blocks. For example to print all your vars:

#define X(var) printf("%d\n", var);
X_LIST_OF_VARS
#undefine X

will generate:

printf("%d\n", my_first_var);
printf("%d\n", another_variable);
printf("%d\n", and_another_one);
Paul Evans
  • 26,111
  • 3
  • 30
  • 50