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

不念不忘少年蓝@ 2023-10-02 20:59 131阅读 0赞

_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(**泛型)的使用** (看完上面的可能还不太清楚,所以直接就用实例说明吧)

  1. #include <stdio.h>
  2. #define CUSTOM_GENERIC(_var_) _Generic((_var_), \
  3. /*signed char*/ signed char : printf("type signed char, var:%d\n", _var_), \
  4. /*signed short*/ signed short : printf("type signed short, var:%hd\n", _var_), \
  5. /*signed int*/ signed int : printf("type signed int, var:%d\n", _var_), \
  6. /*unsigned char*/ unsigned char : printf("type unsigned char, var:%c\n", _var_), \
  7. /*unsigned short*/ unsigned short : printf("type unsigned short, var:%hu\n", _var_), \
  8. /*unsigned int*/ unsigned int : printf("type unsigned int, var:%u\n", _var_), \
  9. /*float*/ float : printf("type float, var:%f\n", _var_), \
  10. /*double*/ double : printf("type double, var:%lf\n", _var_), \
  11. /*default*/ default : printf("type default!") \
  12. )
  13. int main(void)
  14. {
  15. int a = 10;
  16. float f = 100.0f;
  17. CUSTOM_GENERIC(a); // type signed int, var:10
  18. CUSTOM_GENERIC(f); // type float, var:100.000000
  19. CUSTOM_GENERIC(12); // type signed int, var:12
  20. CUSTOM_GENERIC(12L); // type default!
  21. return 0;
  22. }

运行结果:

f6656e414c9440539028019a8710763a.png

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

unsigned(无符号型)的char(字符型),short(短整型),int(整型)

signed(有符号型)的char(字符型),short(短整型),int(整型)

float(单精度浮点数型),double(双精度浮点数型)

其他未类型:如long(长整型), long long int(64位整型)等

举例讲解:

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

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

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

此处为**C11_Generic**的示例代码(要包含math.h,否则找不到abs函数)

  1. #include<stdio.h>
  2. #include<math.h>
  3. #define GENERAL_ABS(x) _Generic((x),int:abs,float:fabsf,double:fabs)(x)
  4. int main(void)
  5. {
  6. printf("intabs:%d\n", GENERAL_ABS(-12));
  7. printf("floatabs:%f\n", GENERAL_ABS(-12.04f));
  8. printf("doubleabs:%f\n", GENERAL_ABS(-13.09876));
  9. int a = 10;
  10. int b = 0, c = 0;
  11. _Generic(a + 0.1f, int:b, float : c, default:b)++;
  12. printf("b=%d,c=%d\n", b, c);
  13. _Generic(a += 1.1f, int:b, float : c, default:b)++;
  14. printf("a=%d,b=%d,c=%d\n", a, b, c);
  15. }

运行结果:

12efd88bf9f64df39e9f52d14b9cc7c6.png

简单讲解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(泛型)里的参数的值

发表评论

表情:
评论列表 (有 0 条评论,131人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C# Generic

    泛型(Generic) 允许您延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候。换句话说,泛型允许您编写一个可以与任何数据类型一起工作的类或方法。

    相关 (Generic) 的优点

    泛型引入前编程的痛点 `JDK 1.5` 版本以前没有泛型,使用 Object 来实现不同类型的处理,有两个缺点 1、每次使用时都需要`强制转换`; 2、在`编译

    相关 【Reflect】(generics)

    Java泛型概述     泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。 这种参数类型可以用在类、接口和方法的创