是否有可能获得联盟内部的变量类型?例如,我有工会:
typedef struct A {
union {
int p;
double d;
} pointer;
int a;
struct A *next;
} myStruct;
我有功能:
myStruct *getMinInList(myStruct *root) {
// do some things to get the smallest value in List,
// simple and I don't write it here because it's not a point
return smallest;
}
有时在union中是整数或者可能是double。是否有可能获得使用的信息?或者我必须写两个函数: 一个用于获取整数列表中的min元素,另一个用于获取list中的min min元素 - double?
答案 0 :(得分:4)
union
本质上不会存储任何额外信息,例如上次写入的成员。除非上下文显而易见,否则您应该在struct
中指定另一个成员,该成员指定使用union
的哪个成员。这可能是您示例中a
的目的,但定义为显式type
的名为enum
的成员会使语义更明显(此类enum
被调用标记的枚举)。然后,您的函数需要检查每个节点使用哪个成员进行最小化计算。
使用额外的type
成员,代码如下所示:
typedef struct A {
union {
int p;
double d;
} pointer;
enum { POINTER_INT = 0, POINTER_DOUBLE } type;
int a;
struct A *next;
} myStruct;
static double get_value(const myStruct *x) {
return x->type == POINTER_DOUBLE ? x->pointer.d : (double)x->pointer.p;
}
myStruct *getMinInList(myStruct *root) {
myStruct *smallest = root;
while (root) {
if (get_value(root) < get_value(smallest)) {
smallest = root;
}
root = root->next;
}
return smallest;
}
如果a
有不同的目的,请添加具有上述语义的type
成员。
注意:这种快速而肮脏的解决方案假设int
类型的所有值都可以在double
类型中准确表示。如果int
和double
都是64位,则不会出现这种情况。在这种情况下,比较接近它们的大整数和双精度是非常麻烦的,因为从int
到double
的转换会截断低位。可以通过测试(int)(double)root->pointer.p == root->pointer.p
来检测这种截断。对于这种情况,这是一个更精细的解决方案,可以很容易地适应任何更长的整数类型:
static double get_value(const myStruct *x, int *adjust) {
if (x->type == POINTER_DOUBLE) {
*adjust = 0;
return x->pointer.d;
} else {
double d = (double)s->pointer.p;
*adjust = x->pointer.p - (int)d;
return d;
}
}
myStruct *getMinInList(myStruct *root) {
myStruct *smallest = root;
while (root) {
int adjust1, adjust2;
double val1 = get_value(root, &adjust1);
double val2 = get_value(smallest, &adjust2);
if (val1 < val2 || (val1 == val2 && adjust1 < adjust2)) {
smallest = root;
}
root = root->next;
}
return smallest;
}
答案 1 :(得分:1)
你不想要一个工会,你想要一个tagged union
使用标记(可能是枚举)来描述union当前持有的值。
typedef struct A
union {
int p;
double d;
} pointer;
//remember which field was last written
enum { P_ACTIVE = 1, D_ACTIVE } tag;
} myStruct;
这种类型在其他语言中更容易表达 例如,在C ++中,您可能想要的类型是variant。