简体   繁体   中英

why (void **) type can be assigned to (void *) or (int *)?

this is my C code:

int main()
{
    void * ptr_void;
    void ** ptr_2void;
    ptr_void = ptr_2void;
    return 0;
}

i am just wondering why this code is valid? i have assigned an (void *) to (void **) , the compiler pass it even without a warning. the type looks mismatch. and the following code that assigning an (void **) to (int *) also works.

int main()
{
    int * ptr_int;
    void ** ptr_2void;
    ptr_int = ptr_2void;
    return 0;
}

anyone is able to figure out what is exactly of (void *) stuff?

void pointers are type converted to pointers to any other data type implicitly. The compiler will not show any warning. Similarly type converting from pointer of any type to void * will also work without a warning.

Other than for void pointers, if you try to convert from one pointer type to another pointer type implicitly a warning will be issued by the compiler.

For example consider the code given below, It will give you the warning " assignment from incompatible pointer type ".

  int *intptr;
  void *voidptr;
  void **vvptr;
  int intval=123;
  voidptr=&intval;
  vvptr=voidptr;
  intptr=vvptr; 

The line of code causing the warning is intptr=vvptr; because intptr is an integer pointer and vvptr is a pointer of type void ** . None of them are void * pointers and thus a warning.

In order to avoid this warning, you have to explicitly type cast the void ** type to int * type. If you change the line intptr=vvptr; to intptr=(int *)vvptr; then the warning will not be shown by the compiler.

It's important to distinguish between a conversion and a cast .

A conversion transforms a value of one type to a value of another type. A cast is an operator (consisting of a type name in parentheses) that explicitly specifies a conversion. A conversion may be either explicit (specified by a cast operator) or implicit. Most pointer conversions require a cast operator; pointer conversions involving void* are the exception to this.

A value of any pointer-to-object type (or pointer-to-incomplete type) may be converted to void* and back to its original type; the resulting pointer is guaranteed to compare equal to the original pointer.

In an assignment (or when passing an argument to a function, or in a return statement), a conversion to or from void* may be done implicitly, with no cast operator.

In your first code sample:

void * ptr_void;
void ** ptr_2void;
ptr_void = ptr_2void;

the assignment is permitted because a void** may be converted to a void* without a cast. There's nothing special about void** here; a pointer to anything may be converted to a void* without a cast. ( void* is a generic pointer type; void** is not a generic pointer-to-pointer type, and in fact there is no generic pointer-to-pointer type.)

In your second code sample:

int * ptr_int;
void ** ptr_2void;
ptr_int = ptr_2void;

the assignment is not valid; it's a constraint violation . There is no implicit conversion between int* and void** , since neither type is void* . Any conforming C compiler must issue a diagnostic message for the assignment. In some cases, the diagnostic may be a warning, and the compiler will probably generate an implicit conversion as if you had written a cast. In other cases, a compiler may require additional options to cause it to diagnose this violation.

Note that the above does not apply to function pointers. Any function pointer type may be converted (with a cast) to any other function pointer type, converting a function pointer to void* or vice versa has undefined behavior (though it may be supported by some compilers).

void** and void* are different types. int* and void** are different types too. But as Barmar says, any data pointer type can be cast to/from void*. That means you can cast int* to void* , but you cannot cast int* to void** , as void** does not have this same special property.

gcc should give a warning:

warning: assignment from incompatible pointer type [enabled by default]

     ptr_int = ptr_2void;

See this question: Passing to void** instead void* makes the compiler complain about types, why?

void * is a type that is implicitly convertible to and from any object pointer type. void ** isn't - so while you can assign a char * to a void *, you can not do the same with char ** and void **.

The reason is that they are incompatible types: char ** points to a char *, void ** points to a void *, so their base types don't match.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM