关于C预处理器的维基百科页面提到了这一点,但IMO并不清楚:
http://en.wikipedia.org/wiki/C_preprocessor#X-Macros
我为我的小组写了一篇关于它的论文;如果你愿意,可以随意使用它。
#define APP_HW_VERSIONS \
X(0, HW_UNKNOWN, UNKNOWN_HW_VER) \
X(8, HW_NO_VERSION, "XDEV") \
X(24, HW_REVA, "REVA") \
X(39, HW_REVB, "REVB") \
X(54, HW_REVD, "REVD") \
X(71, HW_REVE, "REVE") \
X(88, HW_REVF, "REVF") \
X(103,HW_REVG, "REVG") \
X(118,HW_REVH, "REVH") \
X(137,HW_REVI, "REVI") \
X(154,HW_REVJ, "REVJ") \
\
X(255,HW_REVX, "REVX")
#define X(a,b,c) b,
typedef enum {
APP_HW_VERSIONS
} app_hardware_version_t;
#undef X
static app_hardware_version_t read_board_version(
board_aio_id_t identifier,
board_aio_val_t value
)
{
app_hardware_version_t app_hw_version;
#define X(a,b,c) if (value < a) {app_hw_version = b;} else
APP_HW_VERSIONS
#undef X
{
app_hw_version = HW_UNKNOWN;
}
return app_hw_version;
}
switch(ver)
{
#define X(a,b,c) case b: ascii_to_display_string((lcd_char_t *) &app[0], c, HW_VER_STRING_LEN); break;
APP_HW_VERSIONS
#undef X
default:
ascii_to_display_string((lcd_char_t *) &app[0], UNKNOWN_HW_VER, HW_VER_STRING_LEN);
break;
}
switch(ver)
{
#define X(a,b,c) case b: strncpy(&p_data, (const uint8_t *) c, HW_VER_STRING_LEN); break;
APP_HW_VERSIONS
#undef X
default:
strncpy_write(&p_data, (const uint8_t *) UNKNOWN_HW_VER, HW_VER_STRING_LEN);
break;
}
#define CONFIG_ITEMS \
X(1234, DEVICE_ID, uint16_t, 0, 0xFFFF) \
X(1235, NUM_CONNECTIONS, uint8_t, 0, 8) \
X(1236, ENABLE_LOGGING, bool_t, 0, 1) \
X(1237, SECURITY_KEY, uint32_t, 0, 0xFFFFFFFF)
#define X(a,b,c,d,e) CONFIG_ITEM_##b = a,
typedef enum {
CONFIG_ITEMS
} config_item_t;
#undef X
#define X(a,b,c,d,e) \
int get_config_item_##b(void *p_buf) \
{ \
return read_from_key(a, sizeof(c), p_buf); \
}
CONFIG_ITEMS
#undef X
#define X(a,b,c,d,e) \
bool_t set_config_item_##b(void *p_buf) \
{ \
c val = * (c*) p_buf; \
if (val < d || val > e) return FALSE; \
return write_to_key(a, sizeof(c), p_buf); \
}
CONFIG_ITEMS
#undef X
int get_config_item(config_item_t id, void *p_buf)
{
switch (id)
{
#define X(a,b,c,d,e) case a: return read_from_key(a, sizeof(c), p_buf); break;
CONFIG_ITEMS
#undef X
default:
return 0;
}
}
bool_t set_config_item(config_item_t id, void *p_buf)
{
switch (id)
{
#define X(a,b,c,d,e) \
case a: \
{ \
c val = * (c*) p_buf; \
if (val < d || val > e) return FALSE; \
return write_to_key(a, sizeof(c), p_buf); \
}
CONFIG_ITEMS
#undef X
default:
return FALSE;
}
}
void log_config_items(void)
{
#define X(a,b,c,d,e) \
{ \
c val; \
if (read_from_key(a, sizeof(c), &val) == sizeof(c)) \
{ printf("CONFIG_ITEM_##b (##a): 0x%x\n", val); } \
else { printf("CONFIG_ITEM_##b (##a): Failed to read\n"); } \
}
CONFIG_ITEMS
#undef X
}