Void ** pointer and void * [] as function parameters

I get the following warning: incompatible pointer types 'void**' and 'int* [2]' .

When I try to compile the following code:

 #include <stdlib.h> void func1(void *arr[]) { } int main() { int *arr[2]; for (int i = 0; i < 5; i++) { arr[i] = (int*)malloc(sizeof(int)); *(arr[i]) = 5; } func1(arr); } 

Now it works when I produced arr using (void**) and I could not find the reason for this. In addition, I found that I also need to specify the following code:

 #include <stdlib.h> void func1(void **arr) { } int main() { int **arr; int i[] = { 1, 2 }; int j[] = { 3, 4 }; *arr = i; *(arr+1) = j; func1(arr); //Doesn't compile unless I use (void*) or (void**) casting } 

I know that if the function parameter is a pointer to void , we can pass it any pointer we want without casting, because all the pointers are the same size, so why can't I pass a pointer to a pointer in the same way?

+5
source share
2 answers

All types of object pointers, including int * , guarantee that they will be interchangeable with void * , but they are not interchangeable. A representation of type int * should not be the same as a representation of type void * (although in practice it almost always exists), therefore there is no automatic conversion from a pointer to int * (i.e. int ** >) to a pointer to void * (t .e. void ** ). It is unsafe to assume that a pointed thing of one type can be correctly interpreted as a thing of another directed type.

Please note that these are:

If the function parameter is a pointer to void, we can pass it any pointer that we want without casting, because all pointers are the same size

- incorrect characteristic. Pointers do not have to be the same size. It is only required that each object pointer can be converted to void * and vice versa, and that the result of such a round-trip conversion is equal to the original pointer.

Take @Lundin's comments to the heart: arrays are not pointers. Nevertheless, values โ€‹โ€‹of an array type in most cases are divided into pointers, including when they appear as arguments to a function or as the right operand of an assignment operator.

+2
source

There are several issues with your second piece of code:

 void func1(void** arr) { } int main() { int** arr; int i[] = {1,2}; int j[] = {3,4}; *arr = i; *(arr+1) = j; func1(arr); //Doesn't compile unless I use (void*) or (void**) casting } 

You never initialize arr to point to a pointer or an array of pointers to int . It is uninitialized, so its value can be anything. When you set *arr to i , you invoke undefined behavior.

In addition, int ** and void ** are not compatible types, you cannot directly convert them to another. The rationale for this is that on some rare systems, int * and void * may have a different view. Sending a pointer to int * as a pointer to void * would be just as wrong as casting a pointer to float as a pointer to double . On systems where the view is the same, you can simply write an explicit listing.

Here is the corrected version:

 #include <stdlib.h> void func1(void **arr) { } int main(void) { int *int_pointer_array[2]; int **arr = &int_pointer_array; int i[] = { 1, 2 }; int j[] = { 3, 4 }; *arr = i; /* this line modifies int_pointer_array[0] */ *(arr+1) = j; /* this line modifies int_pointer_array[1] */ func1((void **)arr); return 0; } 
+4
source

Source: https://habr.com/ru/post/1241511/


All Articles