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

时间:2018-10-20 17:56:37

标签: c byte dynamic-arrays

我正在用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*进行数据存储。

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

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

从你所拥有的 [a-> data =(void *)val; ]应该可以正常运行。

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

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