热门问题
时间线
聊天
视角
X宏
来自维基百科,自由的百科全书
Remove ads
X宏(X macros)是编程语言宏里的经典用法,可以产生类似列表的数据结构或是程序结构,常用在列表中部分内容无法用indexing合成的情形(例如在编译期就要产生)。若要维护列表,其对应项需要以相同的顺序声明或执行,可以用X宏可靠的维护此部分程序。
这类列表的例如包括数组的初始化(与枚举常量和函数原型的声明一起),叙述序列和switch语句的生成等。
X宏的使用可以追溯到1960年代[1],在现今的C语言和C++语言中仍可使用,但和其他语言特性相比较,知道X宏的人比较少[2][3]。
实现
X宏包括两部分:
- 列表元素的定义
- 列表的展开,产生部分的宣告或是叙述
列表是由宏或是头文件所定义(命名为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);
}
Remove ads
示例2,用X宏为参数
此示例设法提高X宏的可读性:
- 定义列表的宏名称前面加上FOR_。
- 将工作宏以参数方式传递给列表宏。一方面可以避免定义一个名称无法表示用途的宏X,也避免后续需要undefine该宏。
- 使用可变参数宏...的语法在工作宏中,使其在需要时可以接收更多的参数。这可以让程序维护者可以视需要增加字段,但不需更新整个宏的定义。
- 使用名称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 )
}
相关条目
参考资料
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads