我在个人项目中使用tagged unions。例如,这是我使用的代码类型:
struct data_unit {
enum {
d_A, d_B, d_C
} dtype;
union {
char a;
int b;
double c;
} data;
};
void print_data(data_unit du) {
switch (du.dtype) {
case d_A: {
printf("%c", du.data.a);
break;
}
case d_B: {
printf("%d", du.data.b);
break;
}
case d_C: {
printf("%lf", du.data.c);
break;
}
default:
break;
}
return;
};
是否有更有效的方式来实施print_data
,没有人工检查dtype
的每个案例?如果C允许类型列表,我将使用enum
迭代它,但这不是一个可用的实用程序。我需要一种通用的方法来实现这一点,因为我计划在联合中添加大量数据类型。
这可能吗?如果没有,在这种情况下,对我来说,更好的策略是什么?
答案 0 :(得分:2)
您可以利用这样一个事实,即指向struct-object的指针可以被视为指向其第一个成员的指针。因此,在交换dtype
和data
时,您可以通过某种通用方式访问所有成员:
struct data_unit {
union {
char a;
int b;
double c;
} data;
enum {
d_A, d_B, d_C
} dtype;
};
typedef void (print_data_unit) (struct data_unit *du);
void print_data_unit_char(struct data_unit *du) {
printf("%c\n", *((char*)(du)));
}
void print_data_unit_double(struct data_unit *du) {
printf("%lf\n", *((double*)(du)));
}
void print_data_unit_int(struct data_unit *du) {
printf("%d\n", *((int*)(du)));
}
static print_data_unit* functions[3] = { print_data_unit_char, print_data_unit_int, print_data_unit_double };
void print_data(struct data_unit du) {
functions[du.dtype](&du);
}
int main() {
struct data_unit du;
du.dtype = 0;
du.data.a = 'c';
print_data(du);
du.dtype = 1;
du.data.b = 100;
print_data(du);
du.dtype = 2;
du.data.c = 200.55;
print_data(du);
}