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

我见过一个函数,其原型是:

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** ,但它不起作用]

-广告

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

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

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

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

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

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

有一个原因,编译器无法自动从mystruct**void**

请考虑以下代码:

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

编译器不会在*x = *b行中抱怨myotherstruct*void*的隐式myotherstruct* ,即使该行试图在只应该放置mystruct指针的地方放置指向mystruct指针。

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

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

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

转换应该可以工作,但是你需要转换为void ** ,因为这是函数所期望的。

虽然它看起来很脏:有时你不能在不使用void **的情况下解决问题。

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