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

时间:2012-01-27 22:19:34

标签: c void-pointers

我正在尝试使用双void指针,但我对使用情况有点困惑。 我的struct包含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。而不是选择。 ..

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

4 个答案:

答案 0 :(得分:23)

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]

答案 1 :(得分:2)

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

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

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];
}

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


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

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

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

答案 2 :(得分:1)

您使用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*你可以把指针指向任何东西,只是不要忘记在使用它之前强制转换为原始类型;)

答案 3 :(得分:-3)

万能的推!

any_type x ;
void * v = * ( void * * ) & x ;
全能的拉!

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

小心丢失/获得数字