是否可以获取 union 内部的变量类型?例如我有 union :
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 。是否可以获得所使用的信息?或者我必须写两个函数: 第一个用于获取列表中带有整数的最小元素,第二个用于获取列表中的最小元素 - double?
最佳答案
union
本质上不存储任何额外信息,例如最后写入的成员。除非上下文很明显,否则您应该在 struct
中拥有另一个成员来指定使用 union
的哪个成员。这可能是示例中 a
的目的,但是定义为显式 enum
的名为 type
的成员将使语义更加明显(这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 位,则情况并非如此。在这种情况下,比较大整数和接近它们的 double 非常麻烦,因为从 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;
}
关于c union从中获取类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34834253/