Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c

pointers

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?

like image 652
kevin Avatar asked Dec 24 '13 15:12

kevin


2 Answers

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.

like image 144
Deepu Avatar answered Nov 16 '22 00:11

Deepu


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

like image 25
Keith Thompson Avatar answered Nov 16 '22 02:11

Keith Thompson