c union从中获取类型

标签 c types unions

是否可以获取 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 类型准确表示。如果 intdouble 都是 64 位,则情况并非如此。在这种情况下,比较大整数和接近它们的 double 非常麻烦,因为从 intdouble 的转换会截断低位。可以通过测试 (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/

相关文章:

C:逐行读取文件并将数据插入到结构中

c++ - 智能感知 : expression must have integral or enum type

java 。类的类型与对象

haskell - 新类型声明函数?

C enum 打印错误?

c++ - 有人可以解释这个 C++ union 示例吗?

c - 段错误以及如何使用 union 类型

c++ - 在排序数组中找到a [i] = i的最有效方法是什么?

c - 使用 C 对棋盘上图 block 的位置进行排序

ios - 将表示十六进制值的 NSString 转换为十六进制( @"0d"到 0x0d)