[英]Doxygen: Documenting the parameters of a function pointer type (ANSI-C)
[英]Is void** an acceptable type in ANSI-C?
我看过一个函数的原型是:
int myfunc(void** ppt)
在C文件中,此函数称为= myfunc(mystruct ** var1);
其中mystruct是我们拥有的结构之一的typedef。
这在MSVC6.0中没有任何编译错误的情况下有效,但是当我使用其他C编译器对其进行编译时,它在使用错误消息调用此函数的位置给出了错误消息:
mystruct **类型的参数与void **类型的参数不兼容
myfunc()的参数保持为void **,因为它似乎是通用的malloc类型的函数,将使用各种结构变量类型来调用该函数以进行内存分配
mystruct**
,但这没有用] -广告
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);
void**
是有效的,但是根据您的错误消息,您可能必须如下显式转换参数:
mystruct **var1;
x = myfunc ((void**) var1);
这是因为myfunc
函数期望使用void**
类型。 虽然可以将void*
隐式转换为任何其他指针,但对于双指针则不是这样-您需要显式转换它。
编译器无法自动将mystruct**
为void**
是有原因的。
考虑以下代码:
void stupid(struct mystruct **a, struct myotherstruct **b)
{
void **x = (void **)a;
*x = *b;
}
编译器不会抱怨*x = *b
行中从myotherstruct*
隐式myotherstruct*
为void*
,即使该行试图将指向myotherstruct
的指针放在仅应放置指向mystruct
指针的位置。
错误实际上是在上一行中,该行将“指向可以放置指向mystruct
的指针的地方的指针”转换为“指向可以放置指向任何物的指针的地方的指针”。 这就是没有隐式强制转换的原因。 当然,当您使用显式强制转换时,编译器会假定您知道自己在做什么。
这个问题有点令人困惑。 但是,是的, void **
当然是合法有效的C,并且按预期表示“指向void
指针”。
我不确定您的通话示例,参数(“ mystruct ** var1”)没有意义。 如果var1
的类型为mystruct **
,则该调用应仅读取a = func(var1);
mystruct **
,这可能是一个错字。
强制转换应该可以,但是您需要强制转换为void **
,因为这是函数所期望的。
看起来很脏:有时候,如果不使用void **,就无法解决问题。
是的, void **
是完全可以接受的,并且在某些情况下非常有用。 还要考虑给定的声明void **foo
和void *bar
,编译器将知道foo指向的对象的大小(它指向一个指针,除了在一些您需要的古老平台上,所有指针的大小都相同)不必担心),但是它不会知道bar指向的对象的大小(它可以指向任何大小的对象)。 因此,您可以安全地对void **
指针执行指针算术运算,但不能对void *
指针执行指针算术运算。 您必须先将它们转换为其他char *
,例如char *
。 GCC允许您假装void *
和char *
是等效的,每个指向一个对象的大小为单个字节,但这是非标准且不可移植的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.