Is void** an acceptable type in ANSI-C?

前端 未结 6 1858
余生分开走
余生分开走 2021-01-05 10:06

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);<

相关标签:
6条回答
  • 2021-01-05 10:08

    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.

    0 讨论(0)
  • 2021-01-05 10:10

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

    0 讨论(0)
  • 2021-01-05 10:13

    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.

    0 讨论(0)
  • 2021-01-05 10:21

    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.

    0 讨论(0)
  • 2021-01-05 10:25

    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.

    0 讨论(0)
  • 2021-01-05 10:28

    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);
    
    0 讨论(0)
提交回复
热议问题