Enumerations in languages like e.g. Swift or Rust support a kind of hybrid "choice plus data" mechanism, such that I could define a type like:
enum SomeOption {
None,
Index(int),
Key(string),
Callback(fn),
}
Now if I were to implement this in C, my understanding is that something like this would not be valid:
typedef enum {
is_callback_or_none,
is_string,
is_number
} my_choice;
typedef struct {
my_choice value_type;
void* value;
} my_option;
my_option x = {
.value_type = is_number,
.value = (void*)42
};
if (x.value_type == is_number) {
int n = (int)x.value;
// … use n…
}
I'm not sure what exactly I risk in doing this, but according to e.g. Can pointers store values and what is the use of void pointers? the only things I should store in a void*
are actual addresses and NULL
. [Aside: please turn a blind eye to the separate question of storing callback function pointers in a void*
which I forgot was problematic when I made up this example.]
I suppose a more proper way to do this would be to use a union, e.g.:
typedef struct {
my_choice value_type;
union {
int number_value;
char* string_value;
void* pointer_value;
};
} my_option;
…which is probably nicer all around anyway. But I'm wondering specifically about the invalidity of the void* value
version . What if I were (instead of the union
solution) to simply substitute uintptr_t
in place of the void*
?
typedef struct {
my_choice value_type;
uintptr_t value;
} my_option;
Would storing either a pointer to a string/callback/null or a number within the uintptr_t value
field of this struct be valid and [at least POSIX-]portable code? And if so, why is that okay, but not the seemingly equivalent void* value
version?