Wednesday, January 5, 2022

[SOLVED] Way to supress warning for implicit typecasting from void ** to another **?

Issue

I have a little project that includes handling pointer arrays, and to facilitate that I made a .h file that handles it by doing the operations with void pointers then returns the final product, i.e. the function prototype would be something like void **ptr_array_add(void **ptr_array, void *new_ptr);. However, whenever I use this function without explicitly typecasting my pointers to void ** and back to their original type, gcc throws warnings on the conversion.

Is what I'm doing unsafe? I'm assuming that there must be a reason gcc gives me the warning, but as far as I know, void ** is identical to any other kind of pointer array since all pointers are 8 bytes long (or however long they are, the point is they are all the same length), and if what I'm doing has no problems, is there a way to supress the warning without having to add 20 characters of typecasting everytime I call these functions?

Thanks


Solution

If this is an array with one pointer after the other, you could probably change the signature to use void*. I make a simple example, writing the new pointer into the second entry of the array and returning the old start of the array.

void* ptr_array_add(void* ptr_array, void* new_ptr) {
    void** entries = (void**)ptr_array;
    entries[1] = new_ptr;
    return (void*)entries;
}

All the casts are now inside the function. Your user code would have to keep the array as void*.

If you want to also cast the returned value to a specific type, e.g. int**, that cannot be done automatically.

You would have to create specific wrappers for each type you use. With a C++ compiler there would be templates.

For C only you could use preprocessor macros to create wrapper functions automatically.

You can (in C) also use an out parameter for the return value, if you may completely change the function signature:

// out_ptr_array points to a location, where the result is stored
// in your terminology it would be a void***, but we actually use void*
// in_ptr_array is void**, but we actually use void*
// new_ptr is void*

void ptr_array_add(void* out_ptr_array, void* in_ptr_array, void* new_ptr) {
    void** entries = (void**)in_ptr_array;
    entries[1] = new_ptr;
    void** returnarray = (void**)out_ptr_array;
    *returnarray = entries; // of course we can also return a new/another address to an array
}


// no warnings!
#include <stdio.h>
int main() {
    int* array[3]; // array of pointers to int
    int** arrayptrin; // location of array
    arrayptrin = &array[0];

    int** arrayptrout; // return value of function
    int a = 4;         // value
    int* pa = &a;      // pointer to value for adding

    // call function with parameters
    // where to store result (new array location?), array location, new pointer
    ptr_array_add(&arrayptrout, arrayptrin, pa);

    int* pb = arrayptrout[1]; // read one pointer
    printf("Result: %d\n", *pb); // print, value on pointer location (prints: 4)
}

In this example we do not need any casts outside the header function. No warning is issued at all.



Answered By - Sebastian