跳转到内容

X巨集

本页使用了标题或全文手工转换
维基百科,自由的百科全书

X巨集(X macros)是编程语言巨集里的经典用法,可以产生类似列表的资料结构或是程式结构,常用在列表中部份内容无法用indexing合成的情形(例如在编译期就要产生)。若要维护列表,其对应项需要以相同的顺序声明或执行,可以用X巨集可靠的维护此部份程式。

这类列表的例如包括阵列的初始化(与枚举常数和函数原型的声明一起),叙述序列和switch语句的生成等。

X巨集的使用可以追溯到1960年代[1],在现今的C语言C++语言中仍可使用,但和其他语言特性相比较,知道X巨集的人比较少[2][3]

实现

[编辑]

X巨集包括两部份:

  1. 列表元素的定义
  2. 列表的展开,产生部份的宣告或是叙述

列表是由巨集或是标头档所定义(命名为LIST),本身不会产生程式码,只包括了一连串巨集(命名为X)列表,巨集会依该顺序进行,列表中也包括列表元素的资料。每一个引用列表LIST时,会加上要执行的巨集。列表LIST展开时,会将X改为真正要执行的巨集,该巨集就会针对列表的每一个元素依序处理,产生资料或是程式码。

范例1

[编辑]

此例中定义一个变数列表,并且可以自动产生其宣告叙述,以及用printf显示的叙述。

首先是列表定义。列表可以包括多个引数,不过目前只使用变数名称。

#define LIST_OF_VARIABLES \
    X(value1) \
    X(value2) \
    X(value3)

接著将此列表展开,以此产生变数宣告:

#define X(name) int name;
LIST_OF_VARIABLES
#undef X

用类似的方式,可以产生用prints显示变数和值的叙述:

void print_variables(void)
{
#define X(name) printf("%s = %d\n", #name, name);
    LIST_OF_VARIABLES
#undef X
}

透过C预处理器,会产生以下的程式码。其中的换行和缩排是方便阅读才放上去的,预处理器其实不会产生换行和缩排:

int value1;
int value2;
int value3;

void print_variables(void)
{
    printf("%s = %d\n", "value1", value1);
    printf("%s = %d\n", "value2", value2);
    printf("%s = %d\n", "value3", value3);
}

范例2,用X巨集为参数

[编辑]

此范例设法提高X巨集的可读性:

  1. 定义列表的巨集名称前面加上FOR_。
  2. 将工作巨集以参数方式传递给列表巨集。一方面可以避免定义一个名称无法表示用途的巨集X,也避免后续需要undefine该巨集。
  3. 使用可变参数宏...的语法在工作巨集中,使其在需要时可以接收更多的参数。这可以让程式维护者可以视需要增加栏位,但不需更新整个巨集的定义。
  4. 使用名称DO作为列表巨集中引数巨集的名称。
#define FOR_LIST_OF_VARIABLES(DO) \
    DO(id1, name1) \
    DO(id2, name2) \
    DO(id3, name3)

同上,依此表可以产生以下的变数宣告:

#define DEFINE_NAME_VAR(id, name, ...) int name;
FOR_LIST_OF_VARIABLES( DEFINE_NAME_VAR )

或是宣告enumeration:

#define DEFINE_ENUMERATION(id, name, ...) name = id,
enum IdListType
{
    FOR_LIST_OF_VARIABLES( DEFINE_ENUMERATION )
};

用类似方式,也可以产生用printf显示变数和名称的程式。

void print_variables(void)
{
    #define PRINT_NAME_AND_VALUE(id, name, ...) printf(#name " = %d\n", name);
    FOR_LIST_OF_VARIABLES( PRINT_NAME_AND_VALUE )
}

相关条目

[编辑]

参考资料

[编辑]
  1. ^ Meyers, Randy. The New C: X Macros. Dr.Dobb's 2001.
  2. ^ Bright, Walter. The X Macro. Digital Mars 2010
  3. ^ Lucas, Andrew. Reduce C-language coding errors with X macros. Embedded.com 2013