void **是ANSI-C中可接受的类型吗?
我见过一个函数,其原型是:
int myfunc(void** ppt)
该函数在C文件中作为a = myfunc(mystruct ** var1)调用;
其中mystruct是我们拥有的结构之一的typedef。
这在MSVC6.0中没有任何编译错误,但是当我用其他一些C编译器编译它时,它会在调用此函数的地方出错,并显示错误消息:
mystruct类型的参数**与void **类型的参数不兼容
myfunc()的参数保持为void **,因为它似乎是一个通用的malloc类函数,可以使用各种结构变量类型进行内存分配
- 在C标准/任何C编译器中是否允许使用任何类型的void **?
- 我该如何解决? [我尝试将函数调用参数转换为
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 **foo
和void *bar
,编译器将知道foo指向的对象的大小(它指向一个指针,所有指针都是相同的大小,除了你需要的几个古老平台不用担心),但它不会知道bar所指向的对象的大小(它可能指向任何大小的对象)。 因此,您可以安全地对void **
指针执行指针运算,但不能对void *
指针执行指针运算。 你必须先将它们转换为其他东西,比如char *
。 GCC将允许您假设void *
和char *
是等效的,每个都指向一个字节大小的对象,但这是非标准且不可移植的。