Amaterastis
Amaterastis

Reputation: 479

C - Dynamically cast void* in arithmetic

I have a problem at hand and I've sketched a quick program to try describe the issue in easier manner.

Here is a structure I am using. The reason I am using void* is because I want to associate different types with different variables.

struct Test_s
{
    void* value;
    size_t size;
};

Next, I want to write a function which would accept this structure type as an input:

void* func(struct Test_s* t1, struct Test_s* t2)
{
    if (*t1->value != *t2->value)
    {
        return *t1->value;
    }
    else
    {
        return *t2->value;
    }
}

The only way I can make this program compile is if I were to typecast void* to some type. The problem I am facing is that I do not know which type it is therefore I cannot brute force it, e.g.:

*(int*)t1->value != *(int*)t2->value;

(I could deduce it from the size field, this is why I've added it) but I do not know how to dynamically make this typecast. This is possible because it is planned only to use stdint types. How would you solve this problem since it is not possible to pass an argument like (int*), (char*), etc. to a function.

Upvotes: 0

Views: 80

Answers (1)

4386427
4386427

Reputation: 44329

If size tells you the size of the pointed-to-object, you can do:

if (memcmp(t1->value, t2->value, t1->size) != 0) { ... }

But notice that not all object types are comparable using memcmp. For instance two structs-objects with equal member values may have different padding-values and will therefore fail on memcmp. For floats there are also some special values where == and memcmp will give different results. So whether this is a useful solution depends on the types used.

Further, it may be a good idea to check that t1->size == t2->size before calling memcmp.

That said, notice that this is wrong

return *t1->value;

because you defined the function to return a void pointer, i.e. void* func, and *t1->value is not a void-pointer. It's a dereferenced void-pointer which is illegal to do anyway.

A working function could be:

void* func(struct Test_s* t1, struct Test_s* t2)
{
    if (t1->size != t2->size ||
        memcmp(t1->value, t2->value, t1->size) != 0)
    {
        return t1->value;
    }
    else
    {
        return t2->value;
    }
}

Upvotes: 3

Related Questions