7

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

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**,但没有成功]

-广告

4

6 回答 6

22

comp.lang.c FAQ问题 4.9中详细解决了这个问题。简而言之,他们说将任意指针指向 a并不是严格可移植void **的;他们继续解释说“这样的代码可能有效,有时也被推荐,但它依赖于具有相同内部表示的所有指针类型(这是常见的,但不是通用的)。” 他们继续解释说:“void **您使用的任何值都必须是void *某处实际值的地址;像(void **)&dp.

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

some_type *var1 = foo();
void *tmp_void_ptr = (void *)var1;
myfunc(&tmp_void_ptr);
于 2008-10-30T15:51:31.790 回答
8

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

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

那是因为该myfunc函数需要该void**类型。虽然void*可以隐式转换为任何其他指针,但对于双指针而言并非如此 - 您需要显式转换它。

于 2008-10-29T10:03:33.850 回答
3

mystruct**编译器无法自动从to 转换是有原因的void**

考虑以下代码:

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

编译器不会抱怨行中隐式转换 from myotherstruct*to ,即使void**x = *b行试图将指向 a 的指针myotherstruct放在只mystruct应放置指针的位置。

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

于 2008-10-29T10:44:15.483 回答
1

这个问题有点令人困惑。但是,是的,void **当然是合法有效的 C,并且意指“指向指针的指针void”,正如预期的那样。

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

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

于 2008-10-29T10:04:23.600 回答
0

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

于 2008-10-29T10:04:27.717 回答
0

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

于 2008-10-29T20:04:02.217 回答