当前位置:嗨网首页>书籍在线阅读

21-泛型选择(C11)

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

16.6.7 泛型选择(C11)

在程序设计中,泛型编程(generic programming)指那些没有特定类型,但是一旦指定一种类型,就可以转换成指定类型的代码。例如,C++在模板中可以创建泛型算法,然后编译器根据指定的类型自动使用实例化代码。C没有这种功能。然而,C11新增了一种表达式,叫作泛型选择表达式(generic selection expression),可根据表达式的类型(即表达式的类型是 intdouble 还是其他类型)选择一个值。泛型选择表达式不是预处理器指令,但是在一些泛型编程中它常用作 #define 宏定义的一部分。

下面是一个泛型选择表达式的示例:

_Generic(x, int: 0, float: 1, double: 2, default: 3)

_Generic 是C11的关键字。 _Generic 后面的圆括号中包含多个用逗号分隔的项。第1个项是一个表达式,后面的每个项都由一个类型、一个冒号和一个值组成,如 float: 1 。第1个项的类型匹配哪个标签,整个表达式的值是该标签后面的值。例如,假设上面表达式中 xint 类型的变量, x 的类型匹配 int: 标签,那么整个表达式的值就是 0 。如果没有与类型匹配的标签,表达式的值就是 default: 标签后面的值。泛型选择语句与 switch 语句类似,只是前者用表达式的类型匹配标签,而后者用表达式的值匹配标签。

下面是一个把泛型选择语句和宏定义组合的例子:

#define MYTYPE(X) _Generic((X),\
   int: "int",\
   float : "float",\
   double: "double",\
   default: "other"\
)

宏必须定义为一条逻辑行,但是可以用 \ 把一条逻辑行分隔成多条物理行。在这种情况下,对泛型选择表达式求值得字符串。例如,对 MYTYPE(5) 求值得 "int" ,因为值 5 的类型与 int: 标签匹配。程序清单16.13演示了这种用法。

程序清单16.13  mytype.c 程序

// mytype.c
#include <stdio.h>
#define MYTYPE(X) _Generic((X),\
   int: "int",\
   float : "float",\
   double: "double",\
   default: "other"\
)
int main(void)
{
   int d = 5;
   printf("%s\n", MYTYPE(d));    // d 是int类型
   printf("%s\n", MYTYPE(2.0*d)); // 2.0 * d 是double类型
   printf("%s\n", MYTYPE(3L));   // 3L 是long类型
   printf("%s\n", MYTYPE(&d));   // &d 的类型是 int *
   return 0;
}

下面是该程序的输出:

int
double
other
other

MYTYPE() 最后两个示例所用的类型与标签不匹配,所以打印默认的字符串。可以使用更多类型标签来扩展宏的能力,但是该程序主要是为了演示 _Generic 的基本工作原理。

对一个泛型选择表达式求值时,程序不会先对第一个项求值,它只确定类型。只有匹配标签的类型后才会对表达式求值。

可以像使用独立类型(“泛型”)函数那样使用 _Generic 定义宏。本章后面介绍 math 库时会给出一个示例。