cpointersvoid-pointersgcc-warning

Level of type casting of pointers?


I have an array of pointers to structs in C as

typedef struct{

    int elem1;
    char *elem2;

...

}example_t;

example_t *array[MAX_SIZE];

I did generic functions for add or delete pointers to that array like this:

void entryAdd(void *new_entry, const void *any_array[], const int max_entries);

My first try was:

example_t example;
...

entryAdd(&example, array, MAX_ITEMS);

I set the warnings of gcc to -Wall -Wextra and gave me the hint that expected 'const void **' but argument is of type 'example_t **', so I type casted passing in the function:

entryAdd(&example, (void*) array, MAX_ITEMS);

and worked without any warnigs. Then I thought what would happend if I type cast to (void**). The compiler gave me the warning expected 'const void **' but argument is of type 'void **'.

I think the type casting of (void*) cast the pointer pointed by the double pointer to type void*, and (void**) cast the entire double pointer. But I'm not sure.


Solution

  • Generally a value of type void * may be implicitly converted to any other type of pointer to an object type. This is because, if you have the address of something in memory, void *, we can also use the address for something else, some foo *.

    However, a void ** is more than just an address. It says there is something specific in memory, a void *. If we convert it to foo **, that says there is something different in memory, a foo *. In most modern C implementations, a void * and a foo * use the same encodings, but this has not always been the case. A foo * might use a word-based address while a void * might contain additional information to identify a byte within a word. A foo * and a void * might not even be the same size.

    Additionally, even if all pointer types use the same encoding, the fact that void * and foo * have different semantic meanings mean compilers have used them to assume they are different objects, so pointers to them do not ordinarily point to the same memory.

    When the types are void ** and const void **, the C standard does require the types void * and const void * to have the same encoding, but the semantic issues remain. Additionally, there are issues of const correctness, as a const void ** that points to a void * could be used to change that void * to point to an object that is const.

    Because of these things, C does not permit implicit conversions between void ** and foo ** or const void ** without a diagnostic message. You can convert them explicitly with a cast. However, using such converted pointers may fall afoul of C aliasing rules and break your program.