我想编写一个通用函数(例如,接受以void**
类型表示的数组作为参数并对该数组执行某些操作),使得该函数将元素的类型(在此示例中,将是数组中任何元素的类型)作为参数传递。
我可以在C语言中实现吗?
例如:
我想编写一个函数,接受以void**
类型表示的数组作为参数,并以某种随机方式初始化该数组。
所谓“以某种随机方式”,是指一个函数作为参数接收:数组(以void**
类型表示),数组中任何元素的类型,索引(以int
类型表示),并初始化该单元格。
我想编写一个通用函数(例如,接受以void**
类型表示的数组作为参数并对该数组执行某些操作),使得该函数将元素的类型(在此示例中,将是数组中任何元素的类型)作为参数传递。
我可以在C语言中实现吗?
例如:
我想编写一个函数,接受以void**
类型表示的数组作为参数,并以某种随机方式初始化该数组。
所谓“以某种随机方式”,是指一个函数作为参数接收:数组(以void**
类型表示),数组中任何元素的类型,索引(以int
类型表示),并初始化该单元格。
只有在您拥有标准的C编译器的情况下才能实现此功能,这种情况下,您可以使用_Generic
关键字来实现。您必须为每个支持的类型编写不同的函数。
#include <stdio.h>
#define func(x) _Generic((x), int: func_int, char: func_char)(x);
void func_int (int x)
{
printf("%s\t%d\n", __func__, x);
}
void func_char (char x)
{
printf("%s\t%c\n", __func__, x);
}
int main(void)
{
int i = 5;
char c = 'A';
func(i);
func(c);
}
输出:
func_int 5
func_char A
void
的指针,您需要委托给一个了解类型信息的函数。这可以通过回调来实现。例如,标准库函数qsort
接受一个用于比较对象值的回调函数:void qsort( void *ptr, size_t count, size_t size,
int (*comp)(const void *, const void *) );
调用代码提供回调函数,在回调函数内部,将会转换回需要比较的静态类型。这就是通常使用指向 void
的指针的方式,我们以抽象形式定义所需执行的操作集,然后要求调用代码提供这些操作的实现。
#ifndef FUNC_H
#define FUNC_H
#define add(a, b, typename) functionAdd##typename(a,b)
/* function declarations */
#define declared(typename) \
typename functionAdd##typename(typename, typename)
declared(int);
declared(float);
#endif
func.c
#include "func.h"
/* function code */
#define functionAdd(a, b, typename) \
typename functionAdd##typename(typename a, typename b){ \
return a+b; \
}
/* function bodies (definitions) */
functionAdd(a, b, int)
functionAdd(a, b, float)
main.c
#include <stdio.h>
#include "func.h"
int main()
{
int x1 = add(1, 2, int);
float x2 = add(3.0, 4.0, float);
printf("%d %f\n", x1, x2);
return 0;
}
另一种解决方案可能是定义一个枚举来表示这样的类型:
#include "stdio.h"
typedef enum {
TYPE_INT,
TYPE_CHAR,
TYPE_STRING
} type_id;
int print(type_id type, void *data) {
switch (type) {
case TYPE_INT:
// Do something with data as int
printf("%d\n", * (int *)data);
break;
case TYPE_CHAR:
// Do something with data as char
printf("%c\n", * (char *)data);
break;
case TYPE_STRING:
// Do something with data as string
printf("%s\n", (char *)data);
break;
}
}
int main() {
int a = 5;
char b = 'a';
char *c = "string";
print(TYPE_INT, &a);
print(TYPE_CHAR, &b);
print(TYPE_STRING, c);
return 0;
}
我更喜欢 Lundin 的建议,因为它提供了类型安全。
_Generic
编写通用函数,但您几乎必须事先知道您想要泛型化的所有类型。 - Antti Haapala -- Слава Україні