概述
在程序设计中,泛型编程(generic programming)指那些没有特定类型,但是一旦指定一种类型,就可以转换成指定类型的代码。例如,C++ 在模板中可以创建泛型算法,然后编译器根据指定的类型自动使用实例化代
码。
C 没有这种泛型编程。然而,C11 新增了一种表达式,叫作泛型选择表达式(generic selection expression),可根据表达式的类型(即表达式的类型是 int、double 还是其他类型)选择一个值。泛型选择表达式不是预处理器指令,但是在一些泛型编程中它常用作 #define 宏定义的一部分。
下面是一个泛型选择表达式的示例:
_Generic(x, int: 0, float: 1, double: 2, default: 3)
_Generic 是 C11 的关键字。_Generic 后面的圆括号中包含多个用逗号分隔的项。第1个项是一个表达式,后面的每个项都由一个类型、一个冒号和一个值组成,如 float: 1。第1个项的类型匹配哪个标签,整个表达式的值是该标签后面的值。例如,假设上面表达式中 x 是 int 类型的变量,x 的类型匹配 int: 标签,那么整个表达式的值就是 0。如果没有与类型匹配的标签,表达式的值就是 default: 标签后面的值。泛型选择语句与 switch 语句类似,只是前者用表达式的类型匹配标签,而后者用表达式的值匹配标签。
#define MYTYPE(X) _Generic((X),
int: "int",
float : "float",
double: "double",
default: "other"
)
宏必须定义为一条逻辑行,但是可以用 把一条逻辑行分隔成多条物理行。在这种情况下,对泛型选择表达式求值得字符串。例如,对 MYTYPE(5) 求值得 “int”,因为值 5 的类型与 int: 标签匹配。
// 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("%sn", MYTYPE(d)); // d 是int类型
printf("%sn", MYTYPE(2.0*d)); // 2.0 * d 是double类型
printf("%sn", MYTYPE(3L)); // 3L是long类型
printf("%sn", MYTYPE(&d)); // &d 的类型是 int *
return 0;
}
// 输出结果:
int
double
other
other
本来我觉得泛型选择表达式介绍到这里就可以了,大家都很聪明,肯定能举一反三灵活运用了。但是没想到还真有死读书的人跑过来说:不对,你这是误人子弟,泛型选择表达式是用来选择函数的,你用来选择字符串真的是离谱。
这里还是再强调下泛型选择表达式的作用:泛型选择表达式可以根据表达式的类型选择一个值,这个值可以是字符串,也可以是函数,也可以是其他的值。上面的程序已经演示了泛型选择表达式选择字符串,下面再演示下泛型选择表达式选择函数:
#define MYTYPE(X) _Generic((X), int: "int", float : "float", double: "double", default: "other")
#define MYFUNC(X, Y) _Generic((X), int: func_int, double: func_double, float: func_float)(X, Y)
int func_int(int x, int y) {
printf("call func_int.n");
return x + y;
}
double func_double(double x, double y) {
printf("call func_double.n");
return x + y;
}
float func_float(float x, float y) {
printf("call func_float.n");
return x + y;
}
int main() {
int x1 = 2, y1 = 3;
printf("%sn", MYTYPE(3)); // int
printf("%dn", MYFUNC(x1, y1)); // 调用func_int(x1, y1);
return 0;
}
MYTYPE(3)
会被替换为_Generic((3), ...)
,泛型选择表达式根据3选择了int,MYTEPE(3)
就变成了"int"
;MYFUNC(x1, y1)
被替换为_Generic((x1), ...)(x1, y1)
,根据x1的类型,泛型选择表达式选择了func_int,因此MYFUNC(x1, y1)
变成了func_int(x1, y1)
,接下来就是调用func_int函数。
可以发现用泛型选择表达式选择字符串以及选择函数其实没有本质的区别,只是选择函数时最后会有一步调用函数的操作。我们在学习C语言的时候,第一个程序一般都是 Hello,World,在这个程序中就已经接触过如何调用函数以及字符串了:
printf("Hello, World");
有人在评论说我用泛型选择表达式来选择字符串就离谱,我只能说调用个函数真没比字符串难好吧。给你下面这个选择字符串的例子依葫芦画瓢写个选择调用函数的泛型表达式有什么新的知识点吗?
#define MYTYPE(X) _Generic((X), int: "int", float : "float", double: "double", default: "other")
#define MYFUNC(X, Y) _Generic((X), int: func_int, double: func_double, float: func_float)(X, Y)
大家还是要学会举一反三,真别死读书。我只是将知识点分享出来,如何使用还是要靠大家自己练习。
最后
以上就是斯文秀发为你收集整理的C 语言 —— 泛型选择表达式(C11)的全部内容,希望文章能够帮你解决C 语言 —— 泛型选择表达式(C11)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复