C11新增关键字:_Generic(泛型)

1)简单介绍C11

C11标准是ISO/IEC 9899:2011 - Information technology -- Programming languages -- C 的简称,曾用名为C1X
C11标准是C语言标准的第三版,前一个标准版本是C99标准。2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC) 旗下的C语言标准委员会(ISO/IEC JTC1/SC22/WG14)正式发布了C11标准(摘抄C11百度百科)


2)_Generic(泛型)

_Generic是C11新增的一个关键字。其他语言(C++,JAVA...)都有泛型,C或许也要跟下潮流走吧,然后添加了_Generic(泛型)关键字。


_Generic(泛型)的参数:

_Generic ( assignment-expression , generic-assoc-list )

_Generic((var), type1 : ..., type2 : ..., ……, default ...)    此处仅为个人总结的用法

第一个参数assignment-expression(此处的var)为变量,

第二个参数generic-assoc-list(此处的type:...)

type 表示类型,...表示对这个类型的var进行的操作,最终的default表示其他类型,也就是所定义的type中没有的类型,就会跳到default


_Generic(泛型)的使用    (看完上面的可能还不太清楚,所以直接就用实例说明吧)

PS:为了看的清楚使用printf进行格式化输出对不同数据类型的输出处理    (此处使用编译器为Code::Blocks 17.12)

#include <stdio.h>
#include <complex.h>

#define CUSTOM_GENERIC(_var_) _Generic((_var_), \
/*signed char*/                 signed char : printf("type signed char, var:%d\n", _var_), \
/*signed short*/                signed short : printf("type signed short, var:%hd\n", _var_), \
/*signed int*/                  signed int : printf("type signed int, var:%d\n", _var_), \
/*signed long int */            signed long int : printf("type signed long int, var:%ld\n", _var_), \
/*signed long long int*/        signed long long int : printf("type signed long long int, var:%lld\n", _var_), \
/*unsigned char*/               unsigned char : printf("type unsigned char, var:%c\n", _var_), \
/*unsigned short*/              unsigned short : printf("type unsigned short, var:%hu\n", _var_), \
/*unsigned int*/                unsigned int : printf("type unsigned int, var:%u\n", _var_), \
/*unsigned long int*/           unsigned long int : printf("type unsigned long int, var:%lu\n", _var_), \
/*unsigned long long int*/      unsigned long long int : printf("type unsigned long long int, var:%llu\n", _var_), \
/*float*/                       float : printf("type float, var:%f\n", _var_), \
/*double*/                      double : printf("type double, var:%f\n", _var_), \
/*long double*/                 long double : printf("type long double, var:%lf\n", _var_),  \
/*_Bool*/                       _Bool : printf("type _Bool, var:%d\n", _var_),  \
/*float _Complex*/              float _Complex : printf("type float _Complex, var:%f+%fi\n", crealf(_var_), cimagf(_var_)),  \
/*double _Complex*/             double _Complex : printf("type double _Complex, var:%f+%fi\n", creal(_var_), cimag(_var_)),  \
/*long double _Complex*/        long double _Complex : printf("type long double _Complex, var:%lf+%lfi\n", creall(_var_), cimagl(_var_)),  \
/*default*/                     default : printf("type default!") \
)

int main(void)
{
    int a = 10;
    float f = 100.0f;
    float _Complex fCex = 100.0f + 1.0if;

    CUSTOM_GENERIC(a);              //type signed int, var:10
    CUSTOM_GENERIC(f);              //type float, var:100.000000
    CUSTOM_GENERIC(fCex);           //type float _Complex, var:100.000000+1.000000i
    CUSTOM_GENERIC(12);             //type signed int, var:12
    return 0;
}

此处的_Generic(泛型)对以下的类型进行printf格式化输出它们的值:

unsigned(无符号型)的char(字符型),short(短整型),int(整型),long(长整型), long long int(64位整型)

signed(有符号型)的char(字符型),short(短整型),int(整型),long(长整型), long long int(64位整型)

举例讲解:

比如我们此处的,传入了一个a(int(整型))的变量,_Generic就会进行查找generic-assoc-list,是否有对int的处理,如果没有就进行查找是否有default,如果也没有就会抛出异常。

所以我们要首先知道我们会传入哪些类型,然后在_Generic(泛型)中就要对此类型的进行处理

(PS:default不是必须的!!!)


此处为C11中_Generic的示例代码:(摘抄C11百度百科)

#include<stdio.h>

#define GENERAL_ABS(x) _Generic((x),int:abs,float:fabsf,double:fabs)(x)

int main(void)
{
    printf("intabs:%d\n",GENERAL_ABS(-12));
    printf("floatabs:%f\n",GENERAL_ABS(-12.04f));
    printf("doubleabs:%f\n",GENERAL_ABS(-13.09876));
     
    int a=10;
    int b=0,c=0;
    _Generic(a+0.1f,int:b,float:c,default:b)++;
     
    printf("b=%d,c=%d\n",b,c);

    _Generic(a+=1.1f,int:b,float:c,default:b)++;
     
    printf("a=%d,b=%d,c=%d\n",a,b,c);
}

简单讲解C11给出的示例代码:

前三个printf

GENERAL_ABS(-12):执行GENERAL_ABS宏,_Generic(泛型)发现-12是int(整型),然后返回abs(x),x(为传入的值)

GENERAL_ABS(-12.04f) :执行GENERAL_ABS宏,_Generic(泛型)发现-12.04f是float(单精度浮点数型),然后返回fabsf(x),x(为传入的值)

GENERAL_ABS(-13.09876):执行GENERAL_ABS宏,_Generic(泛型)发现-13.09876是double(双精度浮点数型),然后返回fabs(x),x(为传入的值)


_Generic(a+0.1f,int:b,float:c,default:b)++;

首先a为(int(整型)),然后a + 0.1f会被转换成float(单精度浮点数型),所以_Generic(泛型)发现传入的是float(单精度浮点数型),所以执行float的内容,返回一个c,然后跟着++,所以最终变成c++,然后printf格式化输出b=0,c=1


_Generic(a+=1.1f,int:b,float:c,default:b)++;

首先a为(int(整型)),然后a+=1.1f,执行了+=操作并不会改变a的值,执行完后_Generic(泛型)才进行判断a的类型,因为a的类型为int(整型),所以执行int的操作,返回b,然后跟着++,所以最终变成b++,然后printf格式化输出a=10,b=1,c=1

PS:从此可以得知在_Generic(泛型)中执行+= , =等等的操作都不会改变Generic(泛型)里的参数的值



结尾:

看完上面内容是不是觉得_Generic(泛型)在C中好像运用还是不太强呢,其实不然,在后面进行实战项目中会继续使用到_Generic(泛型),可以让你们看到_Generic(泛型)的更多实用方法。故此处就用简单的printf让读者可以简单快速的理解_Generic(泛型)的使用。




猜你喜欢

转载自blog.csdn.net/qq_31243065/article/details/80904613