如何正确使用void **指针?

我试图使用双void指针,但我对使用有点困惑。 我有一个包含void **数组的结构。

 struct Thing{ void ** array; }; struct Thing * c = malloc (sizeof(struct Thing)); c->array = malloc( 10 * sizeof(void *) ); 

所以如果我想为每个指针分配一个不同的对象并尝试检索该值

  // Option 1 *(c->array + index) = (void *) some_object_ptr; // Option 2 c->array[index] = (void *) some_object_ptr; 

然后,我有另一个函数给出(void *) item指向每个单元格,而不是some_object_ptr

如果我想检索some_object_ptr指向的值,
我应该这样做

  function return type is 'void *' and takes argument 'void *' // Option 3 return (void**) item // Option 4 return *((void**)item)? 

奇怪的是,当我使用数组时,数组下标方法我不能使用选项4,只有选项3; 当我使用*(c->array + index)我只能使用opt.4。 而不是选择。 ..

有人可以告诉我这件事吗? 如果我做出任何无效的假设,那么请你纠正我吗?

void **只是一个指向指向具有未指定类型的内存的指针的指针。 你只能解除引用一次(因为你不能取消引用空格void * )。 但是,除此之外,它基本上与任何其他指针类型一样。 如果它对你有所帮助,那么就像使用int *

所以,在您的具体情况下,我们有:

 void** array; int arrayLen = 10; array = (void**)malloc(arrayLen * sizeof(void*)); some_type_t* some_object_ptr; // The following two assignment are equivalent since in C, // array[index] <=> *(array + index) array[index] = (void*)some_object_ptr; *(array + index) = (void*)some_object_ptr; 

然后, array是指向整个数组的指针,而*array是指向第一个元素的指针,因为它等同于array[0]

关于指针的一个快速提示:如果你正在施法,你可能做错了什么。

至于你的问题。 我不确定你的问题是什么item 。 在您的第一部分中,您已经发现了如何访问arrays中的成员。 你可以简单地使用它:

 void *get_item(Thing *c, int index) { return *(c->array + index); // or return c->array[index]; } 

如果需要索引处的指针地址:

 void **get_item_cell(Thing *c, int index) { return c->array + index; // or return &c->array[index]; } 

在第二部分中,您不取消引用指针(对于+选项),或取出数组结果的地址,因为它会自动取消引用它。


编辑:我想我现在知道你想要什么。 你有一个类似于我上面第二个的function,但它是:

 void *get_item_cell(Thing *c, int index) { return (void *)(c->array + index); } 

您想要取消引用此函数返回的值,并访问该对象。 在这种情况下,您只能安全地使用选项4。 由于你没有索引,你不能移动到任何其他单元格(你不知道你是在数组的末尾,还是在开头 – 所以没有添加或减少)。 你只能修复上述函数的错误:cast to void ** ,然后取消引用它: *(void **)item 。 这会给你一个void * 。 如果要访问从此单元格指向的对象,则还需要将其some_object_ptr *obj = *(void**)item转换为正确的类型: some_object_ptr *obj = *(void**)item

你使用void*void**事实并不重要,指针算法仍然可以正常工作,所以你写的两个选项都是正确的。

这是一个例子:

 struct Thing { void ** array; }; struct Object { int i; char c; }; int main () { struct Thing * c = malloc (sizeof(struct Thing)); c->array = malloc(10 * sizeof(void*)); struct Object * o = malloc (sizeof(struct Object)); o->i = 2; o->c = 'a'; *(c->array + 2) = o; printf("Object: i = %d, c = %c\n", ((Object*)c->array[2])->i, ((Object*)c->array[2])->c); free(o); free(c->array); free(c); return 0; } 

因为它是void*你可以把指针指向任何东西,只是不要忘记它在使用前转换为原始类型;)

全能推!

 any_type x ; void * v = * ( void * * ) & x ; 

万能的拉!

 void * v ; any_type x = * ( any_type * ) & v ; 

小心丢失/获得数字