I upvoted Peter's answer, but wanted to point out the possibility of using struct
"inheritance" (also see here) as an alternative solution.
The reason I would suggest this approach is that it provides better type safety during compile time, as we avoid using the void *
pointer and the compiler can check for type errors.
i.e.,:
typedef struct {
int type_id;
int i;
float f;
} common_s;
typedef struct {
common_s parent;
int code;
} type_A_s;
typedef struct {
common_s parent;
char *string;
} type_B_s;
static void func_common(void *a, common_s *b) { /* ... */ }
static void func_a(void *a, type_A_s *b) {
func_common(a, &b->parent);
printf("%d\n", b->code);
}
static void func_b(void *a, type_B_s *b) {
func_common(a, &b->parent);
printf("%s\n", b->string);
}
This is similar to how the kernel handles network socket addresses, where IP4, IP6 and Unix socket address types all have a common header field (which includes the address type identifier), and some functions are common to all types while others use the type identifier to route the address object to the correct function.