union versus void pointer

2019-04-20 10:34发布

What would be the differences between using simply a void* as opposed to a union? Example:

struct my_struct {
    short datatype;
    void *data;
}

struct my_struct {
    short datatype;
    union {
        char* c;
        int* i;
        long* l;
    };
};

Both of those can be used to accomplish the exact same thing, is it better to use the union or the void* though?

标签: c unions
11条回答
家丑人穷心不美
2楼-- · 2019-04-20 10:47

In my opinion, the void pointer and explicit casting is the better way, because it is obvious for every seasoned C programmer what the intent is.

Edit to clarify: If I see the said union in a program, I would ask myself if the author wanted to restrict the types of the stored data. Perhaps some sanity checks are performed which make sense only on integral number types. But if I see a void pointer, I directly know that the author designed the data structure to hold arbitrary data. Thus I can use it for newly introduced structure types, too. Note that it could be that I cannot change the original code, e.g. if it is part of a 3rd party library.

查看更多
倾城 Initia
3楼-- · 2019-04-20 10:53

The union approach requires that you know a priori all the types that might be used. The void * approach allows storing data types that might not even exist when the code in question is written (though doing much with such an unknown data type can be tricky, such as requiring passing a pointer to a function to be invoked on that data instead of being able to process it directly).

Edit: Since there seems to be some misunderstanding about how to use an unknown data type: in most cases, you provide some sort of "registration" function. In a typical case, you pass in pointers to functions that can carry out all the operations you need on an item being stored. It generates and returns a new index to be used for the value that identifies the type. Then when you want to store an object of that type, you set its identifier to the value you got back from the registration, and when the code that works with the objects needs to do something with that object, it invokes the appropriate function via the pointer you passed in. In a typical case, those pointers to functions will be in a struct, and it'll simply store (pointers to) those structs in an array. The identifier value it returns from registration is just the index into the array of those structs where it has stored this particular one.

查看更多
霸刀☆藐视天下
4楼-- · 2019-04-20 10:53

My preference would be to go the union route. The cast from void* is a blunt instrument and accessing the datum through a properly typed pointer gives a bit of extra safety.

查看更多
做个烂人
5楼-- · 2019-04-20 10:54

Toss a coin. Union is more commonly used with non-pointer types, so it looks a bit odd here. However the explicit type specification it provides is decent implicit documentation. void* would be fine so long as you always know you're only going to access pointers. Don't start putting integers in there and relying on sizeof(void*) == sizeof (int).

I don't feel like either way has any advantage over the other in the end.

查看更多
家丑人穷心不美
6楼-- · 2019-04-20 10:54

It's a bit obscured in your example, because you're using pointers and hence indirection. But union certainly does have its advantages.

Imagine:

struct my_struct {
   short datatype;
   union {
       char c;
       int i;
       long l;
   };
};

Now you don't have to worry about where the allocation for the value part comes from. No separate malloc() or anything like that. And you might find that accesses to ->c, ->i, and ->l are a bit faster. (Though this might only make a difference if there are lots of these accesses.)

查看更多
SAY GOODBYE
7楼-- · 2019-04-20 10:55

Although using union is not common nowadays, since union is more definitive for your usage scenario, suits well. In the first code sample it's not understood the content of data.

查看更多
登录 后发表回答