Reputation: 32429
How do I create a list where each element can be of a different type?
What I am doing now is something along these lines:
typedef struct listitem
{
int flavour;
void *payload;
struct listitem *next;
} listitem
And when accessing an item from this list, I check the value of flavour
and then cast payload
to the appropriate type. This approach seems a bit sledge-hammer to me.
What is the standard way to do this in C99?
Is there someway to infer the type of an object, given only its address?
Upvotes: 1
Views: 120
Reputation: 2732
There's another way.
If you don't have many value for your flavour
you can embed it the address. An address aligned to a power of two has its least significant bits to 0.
In C11 you have a standard way of allocating aligned memory which can then be used to tag your pointers.
Upvotes: 1
Reputation: 7943
No, C doesn't provide you with reflection facilities, i.e. the capability to infer the type of an object based on its address. You're going to have to manage that yourself. You're doing the right thing, but you're going to have to manage the flavour yourself. Others have pointed out how to lessen the pain by putting all the alternative types in a union, so that you don't have to cast all the time. You may be well off writing a few inline functions that hide all the unions and what not. To get an idea:
typedef struct listitem
{
int flavour;
union {
int i;
char * str;
};
struct listitem * next;
};
int int_item(struct listitem * item)
{
if (flavour != FLAVOUR_INT)
error("Not an integer");
return item->i;
}
char * string_item(struct listitem * item)
{
if (flavour != FLAVOUR_STRING)
error("Not a string");
return item->str;
}
Upvotes: 3
Reputation: 7044
Pointers you can just use a void *. Other types you can use a union:
typedef struct listitem
{
int flavour; // type of data held
union {
int i;
double d;
float f;
:
:
};
struct listitem *next;
} listitem
Sorry, I misread your question. You have manage flavour yourself.
Upvotes: 1