C语言泛型选择编程

前言

相比C++模板, C语言进行泛型编程没有天然优势, 但并不意味着不能打.

自C11起, C语言已经提供泛型选择功能, 也就是通过系统特性, 不那么顺畅, 但是也勉强可以做一定的泛型了.

同时由于void*的类型抹除性质, 可以做类似C++标准库泛型算法的伪泛型函数.


一、_Generic关键字

_Generic是C11的新特性, 它能根据变量类型, 选择要执行的表达式,

_Generic(expression, type1: code block1, type2: code block2, ..., default: code blockn)

比如最简单的, 打印一个可能是int, 也可能是float 的值:

#include 

#define print(f)                                                               \
    if (_Generic(f, int: 0, float: 1))                                         \
    {                                                                          \
        printf("float = %f\n", f);                                             \
    }                                                                          \
    else                                                                       \
    {                                                                          \
        printf("int = %d\n", f);                                               \
    }

int main()
{
    float f = 5.5F;
    print(f);

    int i = 9;
    print(i);

    return 0;
}

相比C++, 以上代码需要用宏模拟泛型, 比较令人诟病的是debug比较困难, 而且本质上这种泛型没有减少代码量, 也不够自动, 简单代码好说, 复杂代码就比较麻烦了.

二、类型抹除伪泛型

最为典型的是C标准库的qsort()函数, 通过将数组类型抹除为void*, 可以传入任何类型数组, 通过特定的比较函数, 确定类型, 实现泛型功能.

    qsort(void *Base,                                      // 数组地址
          size_t NumOfElements,                            // 元素数量
          size_t SizeOfElements,                           // 元素大小
          int (*PtFuncCompare)(const void *, const void *) // 比较函数
    );

这个用_Generic恐怕就会非常繁琐了, 虽然可以少一个元素大小的参数.


总结

现在不能说C语言没有泛型功能了,只不过和C++相比, 还是有点繁琐, 困难, 难以debug, 但以C的性格, 能加入这种特性, 已经是很给面子了.

你可能感兴趣的:(c)