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

Posted

技术标签:

【中文标题】如何正确使用 void ** 指针?【英文标题】:how to use void ** pointer correctly? 【发布时间】:2012-02-20 21:16:20 【问题描述】:

我正在尝试使用双 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。而不是 opt.3。 ..

谁能告诉我这个?如果我做出任何无效的假设,请您纠正我吗?

【问题讨论】:

也许他需要它? 另外,选项 3 和 4 不一样,3 返回 void**,4 返回 void*item 到底是什么? "那么,我有另一个函数,它给出指向每个单元格的 (void * item),而不是 'some_object_ptr'。" 在 Kevin,抱歉我刚刚编辑了 所以假设它是一个函数,它将 poinere 返回到 some_object_ptr 指向的对象,并且它以 void * 作为指向数组单元格的参数 【参考方案1】:

万能推!

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

万能的拉!

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

谨防丢失/获得数字

【讨论】:

void *v = *(void **) &x;void *v = &x; 之外还有什么用途? &x 的强制转换和取消引用什么都不做。 内存地址没有开始的类型。 @DavidC.Rankin:可以绕过这种方式 C 的限制,不允许将函数指针的值分配给 void-pointer。 只是一个有趣的 * ( void * * ) & ,一种将任何类型转换为 void* 的棘手方法,反之亦然......这个问题没有什么严重的问题,我应该得到 -1 : ) @Fabio 这是未定义的行为,可能会使您的计算机长腿并爬走。将memcpy 用于实现定义的行为,这部分效果更好。【参考方案2】:

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]

【讨论】:

这取决于你想要返回什么。你想返回数组还是数组中的第一个元素。如果你有int* array;,你会选择return array; 还是return array[0];?这里也是一样的。 我想返回单元格中的内容,我认为它是指向另一个对象的 void 指针,返回部分位于不知道索引的不同函数中。取而代之的是 void * item,它指向包含 void 指针的单元格 别忘了检查 malloc 是否真的有效。分配后,您应该检查以下内容:if(array == NULL) return;【参考方案3】:

您使用 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*,所以你可以在那里放置指向任何东西的指针,只是不要忘记在使用它之前将其转换为原始类型;)

【讨论】:

您不必强制转换 malloc() 的返回值。 C 标准明确规定 void * 与 any 指针类型兼容。一些受人尊敬的 C 程序员(例如 Linus Torvalds)和 GNU 等企业反对这种转换,并称其为不好的做法,因为它降低了可读性。 另外,指针运算与整数不同。 AFAIK GCC 假定 void * 是一个字节 ptr,例如,在 32 位系统上, int 是 4 个字节,因此 (int *)ptr + 1 将给出与 (void *)ptr 不同的内存地址+ 1 会。 抱歉,即使我用 C 编写代码,我也习惯使用 Microsoft Visual Studio。编译器不允许我编写 malloc 而不强制转换它的返回值...我编辑了我的答案 @user529758 我说bigthink.com/videos/why-the-programming-language-c-is-obsolete【参考方案4】:

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

至于你的问题。我不确定你的问题是什么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];

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


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

void *get_item_cell(Thing *c, int index)

    return (void *)(c->array + index);

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

【讨论】:

哦,所以返回部分在不同的函数中,它不知道索引和 void * item 指向单元格数组 只有我对你想做的事情的理解。如果您有指针的地址(数组中的一个对象),并且想要返回数组的索引或单元格,则必须循环遍历每个单元格,检查指针对象是否与你想要的,然后返回相关信息。如果这是您想要的,我可以将其添加到我的答案中。

以上是关于如何正确使用 void ** 指针?的主要内容,如果未能解决你的问题,请参考以下文章

如何定义指向函数的指针?

C中结构中的指针-如何将给定的void指针的值分配给结构中的指针[关闭]

如何正确地将指针传递给第 3 方代码的成员函数? [复制]

如何使用来自 Java 的指针传递 Void 参数以及如何为此编写 JNI?

如何使用 void 指针生成 2D 动态数组?

如何将 64 位 void 指针转换为 32 位 void 指针?