关于C之泛型

C11新增了一种表达式,叫作泛型选择表达式

在程序设计中,泛型编程(generic programming)指那些没有特定类型,但是一旦指定一种类型,就可以转换成指定类型的代码。例如,C++在模板中可以创建泛型算法,然后编译器根据指定的类型自动使用实例化代码。在C中这个功能是C11版本才具有的,可根据表达式的类型(即表达式的类型是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"\
)

宏必须定义为一条逻辑行,但是可以用\把一条逻辑行分隔成多条物理行。

#include 
#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

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

可以像使用独立类型(“泛型”)函数那样使用_Generic 定义宏。

我们看一个更具体的例子,更深入了解泛型的作用:

#include 
#include 
#define RAD_TO_DEG (180/(4 * atanl(1)))
// 泛型宏,平方根函数
#define SQRT(X) _Generic(\
    (X),\
    long double: sqrtl, \
    default: sqrt, \
    float: sqrtf)(X)
// 泛型宏,正弦函数,角度的单位为度
#define SIN(X) _Generic(\
    (X),\
    long double: sinl((X)/RAD_TO_DEG),\
    default: sin((X)/RAD_TO_DEG),\
    float: sinf((X)/RAD_TO_DEG)\
)
int main(void) {
    float x = 45.0f;
    double xx = 45.0;
    long double xxx = 45.0L;
    long double y = SQRT(x);
    long double yy = SQRT(xx);
    long double yyy = SQRT(xxx);
    printf("%.17Lf\n", y); // 匹配 float
    printf("%.17Lf\n", yy); // 匹配 default
    printf("%.17Lf\n", yyy); // 匹配 long double
    int i = 45;
    yy = SQRT(i); // 匹配 default
    printf("%.17Lf\n", yy);
    yyy = SIN(xxx); // 匹配 long double
    printf("%.17Lf\n", yyy);
    return 0;
}
6.70820379257202148
6.70820393249936942
6.70820393249936909
6.70820393249936942
0.70710678118654752

直接根据传入的参数,自己不用操心类型,就自动使用相应精度的函数去处理。

你可能感兴趣的:(C语言常见问题及深度解析)