Is this deference of a void pointer correct?

Advertisements

I looked in google and stumbled upon this post, but this does not quite answer my question (or maybe it does I just could not reach there my self). Dereference void pointer

I am trying to create a function that would set pointers of unknown types. Basically:

struct x{
type *links[LINK_SIZE];
// other data
};
somefunc(void *x, void *y void* z)

Here x is a pointer to struct x but passed as void pointer. I want to dereference the void * pointer to access its 1st element which is links. As far as I know all pointers in C are of equal size (Not sure! but at least with gcc compiler). So, In theory, it should work and it works with my gcc compiler. Basically if u dereference a pointer of a struct you get the 1st element in that struct. I was wondering if this is undefined behavior or not?

#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
typedef struct e{
    struct e *links[2];
    int a;
}e;

void somefunc(void *x, void *y, void *z) {
    void **epl = (void **)x;
    epl[0] = y; 
// also see how I am accessing it like a normal array, is this even possible for void pointers?
    epl[1] = z;
}

int main(void) {
    e e1 = (e){{NULL, NULL}, 1};
    e e2 = (e){{NULL, NULL}, 2};
    e e3 = (e){{NULL, NULL}, 3};
    somefunc(&e1, &e2, &e3);    
    printf("%d\n", e1.links[0]->a);
    printf("%d\n", e1.links[1]->a);
    printf("%d\n", e1.a);
    return 0;
}

EDIT:
The actual underlying problem is basically lets say I have 2 different structures.

typedef struct e{
    struct e *links[2];
    int a;
}e;

typedef struct f{
    struct f *links[2];
    float a;
}f;

I want 1 function that would be able to update the links for both the structs rather than having two functions one that cast to f * and other that cast to e *.

>Solution :

The short answer is: You can’t.

The longer answer is that it’s possible to work around the problem and solve it in other ways.

One possible solution is to use a kind of inheritance, by using something called the common initial sequence, where both the structures use a common "base" structure as their first member.

Could be something like this:

typedef struct Base
{
    struct Base *links[2];
} Base;

typedef struct
{
    Base base;
    // Other e members here...
} e;

typedef struct
{
    Base base;
} f;

Now you can create an e object and pass a pointer to it with casting to the function:

void somefunc(Base *object)
{
    // Here you can use object->links[0] and object->links[1]
    // ...
}

int main(void)
{
    e e_object;

    somefunc((Base *) &e_object);
}

Another possibility is to use generic selection:

#define somefunc(x)  _Generic((x), \
      e *: somefunc_e, \
      f *: somefunc_f) \
    (x)

int main(void)
{
    e e_object;
    f f_object;

    somefunc(&e_object);  // Will call somefunc_e(&e_object)
    somefunc(&f_object);  // Will call somefunc_f(&f_object)
}

While it will make the code using the structure seem more generic, you still need to implement the actual functions to handle the different structures.

So this adds more code, but it also makes it possible to do different things for the different types, which is harder with the "inheritance" code.

Leave a ReplyCancel reply