Double pointer conversions that transform into a function with the parameter `const void ** ptr`

GCC gives me the following warning:

note: expected 'const void **' but argument is of type 'const struct auth ** 

Is there any case where this can cause problems?

More fragment

 struct auth *current; gl_list_iterator_next(&it, &current, NULL); 

The function simply stores some void * pointer in current .

+4
source share
2 answers

The error message is clear enough: you are passing struct auth ** where void ** was accepted. There is no implicit conversion between these types, since void* may not have the same size and alignment as other types of pointers.

The solution is to use an intermediate void* :

 void *current_void; struct auth *current; gl_list_iterator_next(&it, &current_void, NULL); current = current_void; 

EDIT : To answer the comments below, here is an example of why this is necessary. Suppose you are on a platform where sizeof(struct auth*) == sizeof(short) == 2 , and sizeof(void*) == sizeof(long) == 4 ; as allowed by the C standard and platforms with different sizes of pointers. Then the OP code will be like running

 short current; long *p = (long *)(&current); // cast added, similar to casting to void** // now call a function that does writes to *p, as in *p = 0xDEADBEEF; // undefined behavior! 

However, this program can also be made to work by entering an intermediate long (although the result may only make sense when the long value is small enough to be stored in short ).

+6
source

Hm ... I think constructs like const void * don't make much sense.

Because if the user wants to access data under void * , he needs casting from void, and this action bypasses the compiler type checks and, therefore, constancy.

Consider the following example:

 #include <stdio.h> #include <stdlib.h> int main () { int i = 6; int * pi = &i; const void * pcv = pi; const int * pci = pi; // casting avoids type checker, so constantness is irrelevant here *(int *)pcv = 7; // here we don't need casting, and thus compiler is able to guard read-only data *pci = 7; return 0; } 

So, the conclusion is that we need either a void pointer, or to ensure data consistency, but not both.

0
source

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


All Articles