利用 _Generic 关键字,可以简单地将一组具有不同类型却有相同功能的函数抽象为一个统一的接口,语法形式如下:
generic-selection:
_Generic (assignment-expression, generic-assoc-list)
generic-assoc-list:
generic-association
generic-assoc-list , generic-association
generic-association:
type-name : assignment-expression
default : assignment-expression
与 sizeof 与 typeof 类似,_Generic 中的 assignment-expression 只用于在编译时获得该表达式的类型,而不会对该表达式做运行时计算,如以下代码所示。
#include <stdio.h> #include <string.h> #include <stddef.h> #include <stdint.h> #define getTypeName(x) _Generic((x), _Bool:"_Bool",/ char: "char", / signed char: "signed char", / unsigned char: "unsigned char", / short int: "short int", / unsigned short int: "unsigned short int", / int: "int", / unsigned int: "unsigned int", / long int: "long int", / unsigned long int: "unsigned long int", / long long int: "long long int", / unsigned long long int: "unsigned long long int", / float: "float", / double: "double", / long double: "long double", / char *: "pointer to char", / void *: "pointer to void", / int *: "pointer to int") int main(void) { char c = 'a'; size_t s; ptrdiff_t p; intmax_t i; int arr[3] = { 0 }; printf("s is '%s'/n", getTypeName(s)); printf("p is '%s'/n", getTypeName(p)); printf("i is '%s'/n", getTypeName(i)); printf("c is '%s'/n", getTypeName(c)); printf("arr is '%s'/n", getTypeName(arr)); printf("0x7FFFFFFF is '%s'/n", getTypeName(0x7FFFFFFF)); printf("0xFFFFFFFF is '%s'/n", getTypeName(0xFFFFFFFF)); printf("0x7FFFFFFFU is '%s'/n", getTypeName(0x7FFFFFFFU)); }
运行结果为:
s is 'unsigned int'
p is 'int'
i is 'long long int'
c is 'char'
arr is 'pointer to int'
0x7FFFFFFF is 'int'
0xFFFFFFFF is 'unsigned int'
0x7FFFFFFFU is 'unsigned int'
除此之外,还必须保证 generic-association-list 中有与 assignment-expression 类型相同的 generic-association 与之对应,否则编译就会报错。例如,在上面代码的main函数中添加如下两行代码:
float *fp=NULL; printf("fp is '%s'/n", getTypeName(fp));
很显然,generic-assoc-list 中没有 generic-association 与 fp 相匹配的类型,从而导致编译出错,如图 1 所示。
图 1 类型不匹配
要解决图 1 这种类型不匹配时导致的编译错误,你可以在 generic-association-list 中添加 default 处理,那么编译就能够顺利进行,如下面的代码所示:
#define getTypeName(x) _Generic((x), _Bool:"_Bool",/ char: "char", / signed char: "signed char", / unsigned char: "unsigned char", / short int: "short int", / unsigned short int: "unsigned short int", / int: "int", / unsigned int: "unsigned int", / long int: "long int", / unsigned long int: "unsigned long int", / long long int: "long long int", / unsigned long long int: "unsigned long long int", / float: "float", / double: "double", / long double: "long double", / char *: "pointer to char", / void *: "pointer to void", / int *: "pointer to int",/ default: "other")
现在,如果编译器发现 generic-assoc-list 中没有 generic-association 与 fp 相匹配的类型时,将默认执行 default 处理,运行结果为:
s is 'unsigned int'
p is 'int'
i is 'long long int'
c is 'char'
arr is 'pointer to int'
fp is 'other'
0x7FFFFFFF is 'int'
0xFFFFFFFF is 'unsigned int'
0x7FFFFFFFU is 'unsigned int'
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/21625.html