开发者

Compilation warning for void ** and void *

开发者 https://www.devze.com 2023-04-06 09:04 出处:网络
I have a question regarding void* and void** and I know this is sort of an old question and has been asked (somewhat) before in stackoverflow. So the question is the following:

I have a question regarding void* and void** and I know this is sort of an old question and has been asked (somewhat) before in stackoverflow. So the question is the following:

When I compile this code with gcc 4.4.3 under ubuntu 10.10, I get the following warning:

zz.c: In function ‘main’:
zz.c:21: warning: passing argument 1 of ‘bar’ from incompatible pointer type
zz.c:9: note: expected ‘void **’ but argument is 开发者_运维技巧of type ‘float **’

why is it that its ok to pass variable x as an argument of foo() but its not ok to pass variable y as an argument of bar(). I can fix this by explicitly casting both variables into void* and void** as expected.

void foo (void* a){
}

void bar(void **a){
     *a = (float *) malloc(100*sizeof(float));
}

int main (){

    float *x = (float*) malloc(100*sizeof(float));
    foo(x);
    free(x);

    float *y;
    bar(&y);
    free(y);

    return 0;
}


void *a means that a points to an object of unknown type. However, a itself is not an unknown type because a is known to have type void*. Only the object that a points to has an unknown type.

void **a means that a points to an object of type void*. The object that *a points to has an unknown type, but the object *a itself is a pointer with type void*.

&y is a pointer to an object of type float*. &y is not a pointer to an object of type void*.


The C++ standard allows for any pointer to be implicitly converted to a void*. But a void** is not the same thing as a void*; it is a pointer to a void*. Therefore, it falls under the rules for regular pointer conversions (ie: forbidden without a cast, with some exceptions).


Adding to the information in the other answers, void* acts as a generic pointer type in C. There are things that are generic about it: any pointer (other than a pointer-to-function type) can be converted to void* and back again without loss of information, and a pointer expression (again, other than pointer-to-function) can be implicitly converted to void*. (C++ has slightly different rules.)

You might think that void** is a generic pointer-to-pointer type, but it isn't. It's a pointer to a specific type, namely to void*. In fact, C doesn't have a generic pointer-to-pointer type. But it does have a generic pointer type, so any code that tries to use void** as a generic pointer-to-pointer type can probably just use void* instead.

0

精彩评论

暂无评论...
验证码 换一张
取 消