C | _Generic泛型选择
Notion链接
_Generic
在 C 语言中被称为泛型选择(Generic Selection)或类型泛型表达式。这是 C11 标准引入的特性。
- 主要用于类型感知的宏编程,实现类似函数重载的效果
- 在编译时处理,编译器会直接替换为对应的表达式
- 基于类型进行选择
- 是一个表达式,会被替换为某个值
示例:
int i = 10;
char *result = _Generic(i,
int: "integer",
float: "float",
default: "other"
);
_Generic
是一个表达式,不是语句,错误示例:
int i = 10;
char *result = _Generic(i,
int: {
printf("It's an integer\\n"); return "integer";
},
float: "float",
default: "other"
);
多行逻辑解决办法
1. 使用函数调用
char* handle_int() {
printf("Processing integer\n");
return "integer";
}
char* handle_float() {
printf("Processing float\n");
return "float";
}
int i = 10;
char *result = _Generic(i,
int: handle_int(), float: handle_float(),
default: "other"
);
2. 使用逗号运算符
int i = 10;
char *result = _Generic(i,
int: (printf("It's an integer\n"), "integer"), float: (printf("It's a float\n"), "float"),
default: "other"
);
3. 结合条件表达式
int i = 10;
char *result = _Generic(i,
int: i > 0 ? "positive integer" : "non-positive integer",
float: "float",
default: "other"
);
4. 如果需要复杂逻辑,建议用宏包装
#define HANDLE_TYPE(x) do { \\
char *result = _Generic((x), \\
int: handle_int(), \\
float: handle_float(), \\
default: "other" \\
); \\
\\
printf("Result: %s\n", result); \\
} while(0)
int i = 10;
HANDLE_TYPE(i);
完整示例
示例1:
#include <stdio.h>
#define TYPE_NAME(x) _Generic((x), \
int: "integer", \
float: "float", \
double: "double", \
char: "character", \
char*: "string", \
default: "unknown type" \
)
int main(void)
{
int num = 100;
float pi = 3.14159f;
double e = 2.71828;
char letter = 'Z';
char *message = "Hello";
printf("num (%d) is a %s\n", num, TYPE_NAME(num));
printf("pi (%.2f) is a %s\n", pi, TYPE_NAME(pi));
printf("e (%.5f) is a %s\n", e, TYPE_NAME(e));
printf("letter ('%c') is a %s\n", letter, TYPE_NAME(letter));
printf("message (\"%s\") is a %s\n", message, TYPE_NAME(message));
return 0;
}
输出:
num (100) is a integer
pi (3.14) is a float
e (2.71828) is a double
letter ('Z') is a character
message ("Hello") is a string
示例2:
#include <stdio.h>
#include <math.h>
int process_int(int x) {
printf("Processing integer: %d\n", x);
return x * x; }
float process_float(float x) {
printf("Processing float: %.2f\n", x);
return sqrtf(x); }
double process_double(double x) {
printf("Processing double: %.6f\n", x);
return log(x); }
char process_char(char x) {
printf("Processing character: '%c'\n", x);
return x >= 'a' && x <= 'z' ? x - 32 : x; }
void process_default(void) {
printf("Processing unsupported type\n");
}
#define PROCESS(x) _Generic((x), \
int: process_int, \
float: process_float, \
double: process_double, \
char: process_char, \
default: process_default \
)(x)
#define MAX(a, b) _Generic((a) + (b), \
int: ((int)(a) > (int)(b) ? (int)(a) : (int)(b)), \
float: ((float)(a) > (float)(b) ? (float)(a) : (float)(b)), \
double: ((double)(a) > (double)(b) ? (double)(a) : (double)(b)), \
default: 0 \
)
#define PRINT_VALUE(x) _Generic((x), \
int: printf("Integer: %d\n", (x)), \
float: printf("Float: %.2f\n", (x)), \
double: printf("Double: %.6f\n", (x)), \
char: printf("Character: '%c' (ASCII: %d)\n", (x), (int)(x)), \
char*: printf("String: \"%s\"\n", (x)), \
default: printf("Unknown type\n") \
)
int main(void)
{
printf("=== 泛型处理函数示例 ===\n");
int i = 5;
float f = 16.0f;
double d = 2.718281828;
char c = 'h';
printf("Original values:\n");
PRINT_VALUE(i);
PRINT_VALUE(f);
PRINT_VALUE(d);
PRINT_VALUE(c);
printf("\nProcessing results:\n");
int result_i = PROCESS(i);
float result_f = PROCESS(f);
double result_d = PROCESS(d);
char result_c = PROCESS(c);
printf("\nProcessed values:\n");
PRINT_VALUE(result_i);
PRINT_VALUE(result_f);
PRINT_VALUE(result_d);
PRINT_VALUE(result_c);
printf("\n=== 泛型最大值函数示例 ===\n");
int max_int = MAX(10, 25);
float max_float = MAX(3.14f, 2.71f);
double max_double = MAX(1.234567, 1.234568);
printf("MAX(10, 25) = %d\n", max_int);
printf("MAX(3.14f, 2.71f) = %.2f\n", max_float);
printf("MAX(1.234567, 1.234568) = %.6f\n", max_double);
printf("\n=== 混合类型示例 ===\n");
char *str = "Hello World";
long long big_num = 9876543210LL;
PRINT_VALUE(str);
PRINT_VALUE(big_num);
return 0;
}
输出:
=== 泛型处理函数示例 ===
Original values:
Integer: 5
Float: 16.00
Double: 2.718282
Character: 'h' (ASCII: 104)
Processing results:
Processing integer: 5
Processing float: 16.00
Processing double: 2.718282
Processing character: 'h'
Processed values:
Integer: 25
Float: 4.00
Double: 1.000000
Character: 'H' (ASCII: 72)
=== 泛型最大值函数示例 ===
MAX(10, 25) = 25
MAX(3.14f, 2.71f) = 3.14
MAX(1.234567, 1.234568) = 1.234568
=== 混合类型示例 ===
String: "Hello World"
Unknown type
- https://en.cppreference.com/w/c/language/generic.html
- Claude Sonnet 4 Thinking