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:%lf\n", _var_), \
/*long double*/ long double : printf("type long double, var:%llf\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位整型)
float(单精度浮点数型),double(双精度浮点数型),long double(多精度浮点数型)
float _Complex,double _Complex,long double _Complex
举例讲解:
比如我们此处的,传入了一个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(泛型)里的参数的值