震惊！！！C语言也能实现泛型编程吗？？

今天看到一个有意思的知识点，赶紧记录一下，总所周知，C 语言没有泛型，但是 C11 新增了一种表达式，叫做泛型选择表达式 (_ Generic)，这个是干啥的呢？它的作用是根据表达式的类型选择一个值，让我们来看一看它具体的语法

泛型选择引入

先看一段代码：

Copy
int main()
{
int x = 1;
double y = 2.0;
char z = 'c';
printf("%d\n", _Generic(x, int:0, double : 1, default:3));
printf("%d\n", _Generic(y, int:0, double : 1, default:3));
printf("%d\n",_Generic(z, int:0, double : 1, default:3));
return 0;
}

_Generic是C11关键字，后面的圆括号中包含有多个用逗号分隔的项，第一个项是表达式，后面的每一个项都由一个类型、一个冒号和一个值组成，如double: 1。第一个项的类型匹配哪一个标签，整个表达式的值就是该标签后面的值

运行结果如下：

可以看到，根据传入的变量的类型，打印的结果也不同，第一个 printf 的第一项 x 是 int，那么整个表达式的结果为 0，第二个 printf 的第一项是 double，表达式的结果就是 1，第三个 printf 打印结果为 3 是因为 char 类型没有匹配，走了默认的 default，结果为 3

其实，这个东西很像 switch 语句，只是 Generic 用表达式类型匹配标签，switch 用表达式的值匹配标签

与宏定义组合

我们可以看到啊，上边的用法还是比较恶心麻烦的，但是呢，我们可以结合宏定义组合去玩这个东西，这样就会非常的方便

直接看例子：

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

int main()
{
int d = 2;
printf("%s\n", MYTYPE(d));
printf("%s\n", MYTYPE(1.0*d));
printf("%s\n", MYTYPE("string"));

return 0;
}

运行结果如下：

与宏定义结合是不是感觉好多了，甚至有点 C++ 泛型编程的感觉了，但是其实还差点。

进阶玩法

_ Generic 标签对应的值，可以是整形，也可以是字符串，当然也可以是函数指针。

我们来看一下下边的这段代码。

Copy
void PrintInt(int x)
{
printf("%d\n", x);
}
void PrintDouble(double x)
{
printf("%lf\n", x);
}
void PrintSting(char* x)
{
printf("%s\n", x);
}

void PrintOther(void x)
{
print("类型有点问题\n");
}
#define PRINT(X) _Generic((X),\
int:PrintInt,\
double:PrintDouble,\
const char*:PrintSting,\
default:PrintOther)(X)

int main()
{
int x = 1;
int y = 2.0;
const char* str = "hello _Generic";
PRINT(x);
PRINT(y);
PRINT(str);
return 0;
}

运行结果如下：

这样是不是和 C++ 的泛型编程很像了呢，是不是挺有意思的，当然还是 C++ 的泛型好用一些。