void **是ANSI-C中可接受的类型吗?

时间:2008-10-29 09:59:28

标签: c void

我见过一个原型为:

的函数
int myfunc(void** ppt)

此函数在C文件中调用为     a = myfunc(mystruct ** var1);

其中mystruct是我们拥有的结构之一的typedef。

这在MSVC6.0中没有任何编译错误,但是当我用其他C编译器编译它时,它会在调用此函数的地方出错,并显示错误消息:

类型为mystruct **的参数与void **

类型的参数不兼容

myfunc()的参数保持为void **,因为它似乎是一个通用的malloc类函数,可以使用各种结构变量类型进行内存分配

  1. C标准/任何C编译器中是否允许使用void **等类型?
  2. 我该如何解决这个问题? [我尝试将函数调用参数转换为mystruct**,但它不起作用]
  3. -AD

6 个答案:

答案 0 :(得分:22)

comp.lang.c FAQQuestion 4.9中详细说明了此问题。简而言之,他们说它不是严格的可移植性来向void **投射任意指向指针的指针;他们接着解释说“像这样的代码可能有用,有时也会被推荐,但它依赖于具有相同内部表示的所有指针类型(这是常见的,但不是通用的)。”他们接着解释说“你玩的任何void **值必须是某个地方实际void *值的地址;像(void **)&dp这样的转换,虽然它们可能会关闭编译器,但是不可移植(甚至可能不会做你想要的)。“

因此,您可以安全/可移植地使用以下代码实现所需的行为:

some_type *var1 = foo();
void *tmp_void_ptr = (void *)var1;
myfunc(&tmp_void_ptr);

答案 1 :(得分:8)

void** 有效,但根据您的错误消息,您可能必须按如下方式显式转换参数:

mystruct **var1;
x = myfunc ((void**) var1);

那是因为myfunc函数期待void**类型。虽然void*可以隐式地转换为任何其他指针,但对于双指针则不然 - 你需要显式地转换它。

答案 2 :(得分:3)

编译器无法自动从mystruct**投射到void**

请考虑以下代码:

void stupid(struct mystruct **a, struct myotherstruct **b)
{
    void **x = (void **)a;
    *x = *b;
}

编译器不会抱怨myotherstruct*行中从void**x = *b的隐式强制转换,即使该行试图将指针指向myotherstruct在一个只能放置mystruct指针的地方。

错误实际上是在上一行中,它将“指向mystruct指针的地方的指针”转换为指向指向任何东西的地方的指针可以放“。 这个是没有隐式演员的原因。当然,当您使用显式强制转换时,编译器会假定您知道自己在做什么。

答案 3 :(得分:1)

这个问题有点令人困惑。但是,void **肯定是合法且有效的C,并且意味着“指向void的指针”。

我不确定你的调用示例,参数(“mystruct ** var1”)没有意义。如果var1的类型为mystruct **,则调用只应为a = func(var1);,这可能是一个错字。

转换应该有效,但你需要转换为void **,因为这是函数所期望的。

答案 4 :(得分:0)

尽管看起来很脏但有时候如果不使用void **就无法解决问题。

答案 5 :(得分:0)

是的,void **完全可以接受,在某些情况下非常有用。同时考虑到声明void **foovoid *bar,编译器将知道foo指向的对象的大小(它指向一个指针,所有指针都是相同的大小,除了一些古代您不必担心的平台),但它不知道bar指向的对象的大小(它可能指向任何大小的对象)。因此,您可以安全地对void **指针执行指针运算,但在void *指针上。您必须先将它们转换为其他内容,例如char *。 GCC将允许您假装void *char *是等效的,每个对象指向一个字节大小的对象,但这是非标准且不可移植的。