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

发布于 2024-07-08 13:48:32 字数 580 浏览 7 评论 0原文

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

int myfunc(void** ppt)

This function is called in a C file as a = myfunc(mystruct **var1);

其中 mystruct 是我们拥有的结构之一的 typedef。

这在 MSVC6.0 中没有任何编译错误,但是当我用其他一些 C 编译器编译它时,它在调用该函数的地方给出错误,并显示错误消息:

Argument of type mystruct ** is incomplete with类型为 void ** 的

参数 myfunc() 的参数保留为 void** 因为它似乎是一种通用的 malloc 类型的函数,可以使用各种结构变量类型来调用以进行内存分配

  1. 是否有任何类型,例如C 标准/任何 C 编译器允许 void ** 吗?
  2. 我该如何解决? [我尝试将函数调用参数转换为 mystruct**,但它不起作用]

-AD

I have seen a function whose prototype is:

int myfunc(void** ppt)

This function is called in a C file as
a = myfunc(mystruct **var1);

where mystruct is typedef for one of structure we have.

This works without any compilation errors in MSVC6.0, But when I compile it with some other C compiler, it gives an error at the place where this function is called with error message:

Argument of type mystruct ** is incompatible with parameter of type void **

The argument of myfunc() is kept as void** because it seems to be a generic malloc kind of function to be called with various structure variable types for memory allocation

  1. Is there any type such as void ** allowed in C standard/any C compilers?
  2. How do I fix this? [I tried casting the function call argument to mystruct**, but it didn't work]

-AD

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

暮年慕年 2024-07-15 13:48:32

comp.lang.c 常见问题解答问题 4.9。 简而言之,他们说将任意指针到指针转换为void **不是严格可移植的; 他们继续解释说“这样的代码可能有效并且有时被推荐,但它依赖于具有相同内部表示的所有指针类型(这是常见的,但不是通用的)。” 他们继续解释说“您使用的任何 void ** 值都必须是某处实际 void * 值的地址;类似于 (void ** )&dp,尽管它们可能会关闭编译器,但它们是不可移植的(甚至可能无法执行您想要的操作)。”

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

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

The comp.lang.c FAQ addresses this issue in detail in Question 4.9. In short, they say it's not strictly portable to cast an arbitrary pointer-to-pointer to a void **; they go on to explain that "code like this may work and is sometimes recommended, but it relies on all pointer types having the same internal representation (which is common, but not universal)." They go on to explain that "any void ** value you play with must be the address of an actual void * value somewhere; casts like (void **)&dp, though they may shut the compiler up, are nonportable (and may not even do what you want)."

So, you can safely/portably achieve the desired behavior with code like:

some_type *var1 = foo();
void *tmp_void_ptr = (void *)var1;
myfunc(&tmp_void_ptr);
脱离于你 2024-07-15 13:48:32

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

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

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

void** is valid but, based on your error message, you probably have to explicitly cast the argument as follows:

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

That's because the myfunc function is expecting the void** type. While void* can be implicitly cast to any other pointer, that is not so for the double pointer - you need to explicitly cast it.

乜一 2024-07-15 13:48:32

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

考虑以下代码:

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

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

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

There is a reason the compiler cannot automatically cast from mystruct** to void**.

Consider the following code:

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

The compiler will not complain about the implicit cast from myotherstruct* to void* in the *x = *b line, even though that line is trying to put a pointer to a myotherstruct in a place where only pointers to mystruct should be put.

The mistake is in fact in the previous line, which is converting "a pointer to a place where pointers to mystruct can be put" to "a pointer to a place where pointers to anything can be put". This is the reason there is no implicit cast. Of course, when you use a explicit cast, the compiler assumes you know what you are doing.

闻呓 2024-07-15 13:48:32

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

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

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

This question is slightly confusing. But yes, void ** is certainly legal and valid C, and means "pointer to pointer to void" as expected.

I'm not sure about your example of a call, the arguments ("mystruct **var1") don't make sense. If var1 is of type mystruct **, the call should just read a = func(var1);, this might be a typo.

Casting should work, but you need to cast to void **, since that is what the function expects.

清君侧 2024-07-15 13:48:32

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

As dirty as it may look like: sometimes you can't solve a problem without using void **.

梅窗月明清似水 2024-07-15 13:48:32

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

Yes, void ** is perfectly acceptable and quite useful in certain circumstances. Also consider that given the declaration void **foo and void *bar, the compiler will know the size of the object pointed to by foo (it points to a pointer, and all pointers are the same size except on a few ancient platforms you needn't worry about), but it will not know the size of the object pointed to by bar (it could point to an object of any size). You can therefore safely perform pointer arithmetic on void ** pointers but not on void * pointers. You must cast them to something else first, like a char *. GCC will allow you to pretend that void * and char * are equivalent, each pointing to an object a single byte in size, but this is nonstandard and nonportable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文