文章目录
- ⭐语法
- ⭐举例
- 🚩判断对象类型
- 🚩判断指针
- 🚩函数重载
- 🚩嵌套使用
- END
⭐语法
Ref: 泛型选择 (C11 起) - cppreference.com
关键词:
- Generic
- default
_Generic(控制表达式 , 关联列表) (C11 起)
关联列表
类型名:表达式
- 类型名:任何并非可变修改的完整对象类型(即既非 VLA 亦非指向 VLA 的指针)。
- 表达式:任何类型和值类别的表达式(除了逗号运算符)
default:表达式
控制表达式
- 任何表达式(除了逗号运算符),若不使用
default
关联,则其类型必须与 类型名 之一兼容。
判定解释
控制表达式 的类型经历左值转换。
只在类型域中进行转换
- 舍弃顶层 cvr 限定符和原子属性
- 数组到指针/函数到指针变换
- 不实例化任何副效应或计算任何值
有类型匹配,若其类型与各关联之一的 类型名 兼容,则解释为冒号后的表达式。
无类型匹配,且提供了 default
关联,则解释为其后的表达式。
注意
关联列表 中的任意二个 类型名 不能指定兼容类型。
使用关键词 default
的关联只能有一个。若不使用 default
,且无一 类型名 与控制表达式类型兼容,则程序无法编译。
⭐举例
🚩判断对象类型
_Generic
可以判断自定义类型。
cvr
限定符对类型识别不受影响。
default
不是必须写道最后一个,顺序这方面没有限制。
#include <stdbool.h>
#include <stdio.h>
struct Node {};
#define get_typename(x) \
_Generic((x), \
default: "other", \
_Bool: "bool", \
int: "int", \
char: "char", \
struct Node: "struct Node" \
)
int main() {
_Bool b = true;
char c = 'a';
const int i = 10;
struct Node node;
printf("Type of [_Bool] is %s\n", get_typename(b));
printf("Type of [char] is %s\n", get_typename(c));
printf("Type of [int] is %s\n", get_typename(i));
printf("Type of [struct Node] is %s\n", get_typename(node));
}
🚩判断指针
对指针类型的判断仍然使用。
#include <stdio.h>
#define get_pointname(x) \
_Generic((x), \
int*: "int*", \
void*: "void*", \
default: "other" \
)
int main() {
int i = 0;
int* ip = NULL;
void* vp = NULL;
printf("Type of [int] is [%s]\n", get_pointname(i));
printf("Type of [int*] is [%s]\n", get_pointname(ip));
printf("Type of [void*] is [%s]\n", get_pointname(vp));
}
🚩函数重载
可以根据类型指定调用的函数,注意参数个数。
下方代码展示在使用_Generic
时,并且直接调用的情况。_Generic((x), default: fun)(x)
。
#include <math.h>
#include <stdio.h>
int default_fun() {
printf("Line[%d], Func[%s]\n", __LINE__, __func__);
return -1;
}
#define sqrt(x) \
_Generic((x), \
float: sqrtf, \
double: sqrt, \
long double: sqrtl, \
default: default_fun \
)(x)
int main(void) {
int i = 4;
float f = 4.0f;
double d = 4.0;
long double ld = 4.0L;
printf("[i] sqrt = %d\n", sqrt(i));
printf("[float] sqrt = %f\n", sqrt(f));
printf("[double] sqrt = %lf\n", sqrt(d));
printf("[long double] sqrt = %Lf\n", sqrt(ld));
}
🚩嵌套使用
由于每次_Generic
只能判断一个表达式的类型,因此如果是需要用到多参的话,可以嵌套的使用_Generic
。
#include <stdio.h>
#define add(x, y) \
_Generic((x), \
int: _Generic((y), \
int: (int)(x) + (int)(y), \
default: (int)(x) + (double)(y) \
), \
default: _Generic((y), \
int: (double)(x) + (int)(y), \
default: (double)(x) + (double)(y) \
) \
)
int main() {
int i1 = 10;
int i2 = 20;
double d1 = 3.14;
double d2 = 2.71;
printf("%d + %d = %d\n", i1, i2, add(i1, i2)); // 整数加法
printf("%f + %f = %f\n", d1, d2, add(d1, d2)); // 浮点数加法
printf("%d + %f = %f\n", i1, d2, add(i1, d2)); // 混合加法
}
END
关注我,学习更多C/C++,算法,计算机知识
B站:
👨💻主页:天赐细莲 bilibili