Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
341 views
in Technique[技术] by (71.8m points)

include - What is a good reference documenting patterns of use of X-Macros in C (or possibly C++)?

A basic definition and example and a few references for "X-Macros" is given in this wikipedia entry on the C pre-processor:

An X-Macro is a header file (commonly using a ".def" extension instead of the traditional ".h") that contains a list of similar macro calls (which can be referred to as "component macros").

What are some good sources of information on how to use this powerful technique? Are there well-known open source libraries using this method?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I use X Macros() in code a lot. The value comes from only adding new data only to the "X list" and not modifying any other code.

The most common use of X Macros() is for associating error text with error codes. When new error codes are added, programmers must remember to add the code and the text, typically in separate places. The X Macro allows the new error data to be added in a single place and get automatically populated anywhere it is needed.

Unfortunately, the mechanisms use a lot of pre-compiler magic that can make the code somewhat hard to read (e.g. string joining with token1##token2, string creation with #token). Because of this I typically explain what the X Macro is doing in the comments.

Here is an example using the error/return values. All new data gets added to the "X_ERROR" list. None of the other code hast to be modified.

/* 
 * X Macro() data list
 * Format: Enum, Value, Text
 */
#define X_ERROR 
  X(ERROR_NONE,   1, "Success") 
  X(ERROR_SYNTAX, 5, "Invalid syntax") 
  X(ERROR_RANGE,  8, "Out of range")

/* 
 * Build an array of error return values
 *   e.g. {0,5,8}
 */
static int ErrorVal[] =
{
  #define X(Enum,Val,Text)     Val,
   X_ERROR
  #undef X
};

/* 
 * Build an array of error enum names
 *   e.g. {"ERROR_NONE","ERROR_SYNTAX","ERROR_RANGE"}
 */

static char * ErrorEnum[] = {
  #define X(Enum,Val,Text)     #Enum,
   X_ERROR
  #undef X
};

/* 
 * Build an array of error strings
 *   e.g. {"Success","Invalid syntax","Out of range"}
 */
static char * ErrorText[] = {
  #define X(Enum,Val,Text)     Text,
   X_ERROR
  #undef X
};

/* 
 * Create an enumerated list of error indexes
 *   e.g. 0,1,2
 */
enum {
  #define X(Enum,Val,Text)     IDX_##Enum,
   X_ERROR
  #undef X
  IDX_MAX   /* Array size */
};

void showErrorInfo(void)
{
    int i;

    /* 
     * Access the values
     */
    for (i=0; i<IDX_MAX; i++)
        printf(" %s == %d [%s]
", ErrorEnum[i], ErrorVal[i], ErrorText[i]);

}

You can also use X Macros() to generate code. For example to test if an error value is "known", the X Macro can generate cases in a switch statement:

 /*
  * Test validity of an error value
  *      case ERROR_SUCCESS:
  *      case ERROR_SYNTAX:
  *      case ERROR_RANGE:
  */

  switch(value)
  {

  #define X(Enum,Val,Text)     case Val:
   X_ERROR
  #undef X
         printf("Error %d is ok
",value);
         break;
      default:
         printf("Invalid error: %d
",value);
         break;
  }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...