我见过一个原型为:

的函数
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

有帮助吗?

解决方案

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

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

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

其他提示

comp.lang.c常见问题解答问题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;
}

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

错误实际上是在上一行中,它正在转换“指向 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 * 是等效的,每个都指向一个大小为单个字节的对象,但这是非标准且不可移植的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top