cpointers

Write reusable pointer type casting logic in a function or macro


Here is the context of my question. I have this code :

typedef enum DType { float32 } DType;

typedef struct Array {
    void *data;
    DType dtype;
    ...
} Array;

The whole idea is to cast the pointer data to the adequate type depending on the value of the field dtype. Although it is possible to just switch on the dtype everytime it is needed, I would like to know if it's possible to have a function / macro encapsulating that logic and usable anywhere needed.

To further illustrate, here is a non-solution I came up with :

void *cast_data_pointer(Array *arr) {
    switch (arr->dtype) {
        case float32:
            return (float *) arr->data;
        default:
            exit(1);
    }
}

Although the type casting logic is correct, it cannot be used because it requires to know in advance which pointer type will be returned :

Array arr = ...; # with dtype float32
void *data_ptr;

data_ptr = cast_data_pointer(&arr); # wrong because data_ptr is still a void pointer
Array arr = ...; # with dtype float32
float *data_ptr;

data_ptr = cast_data_pointer(&arr); # wrong because it required to know in advance that the function will return a float pointer

Having such a function / macro would avoid repetition as well as would be more flexible when I'll add more dtypes to the DType enum in the future.


Solution

  • The whole idea is to cast the pointer data to the adequate type depending on the value of the field dtype. Although it is possible to just switch on the dtype everytime it is needed, I would like to know if it's possible to have a function / macro encapsulating that logic and usable anywhere needed.

    No, not as you seem to mean.

    It is not possible to do what you want with a macro, because macros work at compile time, consuming and producing source code. They know nothing about the values of variables, and that's the basis on which you say you want to make decisions.

    You also cannot do it with a function, because you run into the issue described in the question: you need to know the chosen data type in order to interpret the function result, or else work with a function result such as a tagged union that leaves you in the same place you started.

    More generally, in C, every expression has a data type that is known at compile time, and which therefore cannot vary according to the runtime value of any variable. Choosing behavior based on variables' values requires using conditional statements and / or conditional expressions.

    I could imagine various kinds of macro tooling with which you could ease generating the kind of conditional code you will need, but details are situation specific.


    On the other hand, you might want to consider approaching the problem in a different way. There are several alternatives to consider, such as: