如何在运行时将任何类型存储在 void* 中?

How to store any type in void* at runtime?

我正在用 C:

编写一个动态数组
struct array {
  int len;
  int cap;
  void *data;
};

如果我知道类型就很容易存储值:

void set(array* a, int idx, int val) {
    ((int*)a->data)[idx] = val;
}

但我想接受任何类型 (void*):

void set(array* a, int idx, void* val) {
    a->data[idx] = val;
}

这显然无法编译,因为 'void' is not assignable

据我了解,编译器需要有关类型的信息来获取其大小并计算偏移量以访问数据。

有什么办法可以自己完成吗?直接对字节进行操作,类似

void set(array* a, int idx, void* val, int size) {
    *((char*)a->data + size * idx) = val;
}

基本上我想让它们类似于 Go 切片。您可以在此处阅读有关它们的内置泛型类型的信息:

https://dave.cheney.net/2018/05/29/how-the-go-runtime-implements-maps-efficiently-without-generics

没有模板,没有拆箱。他们使用 void* 进行数据存储。

首先,您需要使用 void* * 数据来存储数组,而不是指向元素的单个指针。

从你所拥有的 [a->data = (void*)val; ] 应该 运行 没问题。

它只是一个指向数据的指针,可以存储为void。当您想要取消引用数据时,您将需要知道如何读取数据。

如果 val 指向一个 int- 为了读取它,您必须强制转换它以让编译器知道要读取多少字节。 所以 : *(int *)(a->data);

我想 memcpy 应该可以满足您的需求:

void set(array* a, int idx, void* val, int size) {
    memcpy(a->data + size * idx, val, size);
}