如何在struct中使用union,并使用不同的union类型键入dede每个struct?

时间:2011-09-13 20:08:46

标签: c

我想创建一个链表,但我希望数据字段为int或float。我写了一些如下代码:

union int_or_float
{
    int int_member;
    float float_member;
};

struct node 
{
    union int_or_float data;
    struct node *next;
};

我想写点:

typedef struct node item; 

但如何指定哪个类型在联合中我喜欢的项目是什么?

7 个答案:

答案 0 :(得分:3)

你没有。工会的根本之处在于它可以是你投入的任何数据。

如果你写信给int_member,那么它将持有一个int。

如果你写信给float_member,它会持有一个浮点数。 (如果你随后从int_member读到了所有地狱,那么它就会崩溃。)

答案 1 :(得分:2)

您无需“指定”任何内容。您只需将值存储在union的相应成员中。

但是,您的结构似乎可以作为某些列表中的节点。如果您的列表旨在同时包含不同类型的值,那么您当然需要某种方法来确定列表中每个元素当前包含的类型。这只能手动完成。即您有责任以某种方式将该信息存储在每个列表项中。例如,您可以在结构中添加type字段

struct node 
{
    enum { INT, FLOAT } type;
    union int_or_float data;
    struct node *next;
};

...

struct node *p;

p = malloc(sizeof *p);
p->type = INT;
p->data.i = 42;
/* ... and add it to the list */

p = malloc(sizeof *p);
p->type = FLOAT;
p->data.f = 3.14;
/* ... and add it to the list */

答案 2 :(得分:1)

当您添加额外的存储空间和条件以检查联合是否存储intfloat时,您可能只是将字段更改为double然后您可以轻松适应任何适合intfloat的值,而不必担心它是哪种类型(在int为32位且double为的大多数实现中IEEE 754双精度)。我认为这将是一个更清洁的设计...

答案 3 :(得分:0)

你想要这样的东西:

#include <stdio.h>

union int_or_float
{
    int int_member;
    float float_member;
};

struct node 
{
    union int_or_float data;
    struct node *next;
};

int main()
{

    typedef struct node item;

    item one;
    one.data.int_member = 10;

    item two;
    two.data.float_member = 10.f;

    printf("%d", one.data.int_member);
    printf("%f", two.data.float_member);

    return 0;
}

答案 4 :(得分:0)

访问数据时会自动完成。联盟只不过是一种投射指针的方式。

#include <stdio.h>

union number {
  int i;
  float f;
};

struct node {
  union number data;
  struct node *next;
};

typedef struct node item;

int main(void) {
  item myItem;

  myItem.data.i = 12; /* Now contains an int */
  myItem.data.f = 12.0; /* Now contains a float */
  printf("location of myItem.data is %p\n", &myItem.data);
  printf("location of myItem.data.f is %p\n", &myItem.data.f);  
  printf("myItem.data is %f\n", *(float *)(&myItem.data));
  printf("myItem.data.f is %f\n", myItem.data.f);
  printf("sizeof(myItem.data) is %lu\n", sizeof(*(float *)(&myItem.data)));
  printf("sizeof(myItem.data.f) is %lu\n", sizeof(myItem.data.f));

  return 0;
}

这将输出

location of myItem.data is 0x7fff5fbff9f0
location of myItem.data.f is 0x7fff5fbff9f0
myItem.data is 12.000000
myItem.data.f is 12.000000
sizeof(myItem.data) is 4
sizeof(myItem.data.f) is 4

在具有gcc版本4.2.1的Intel Mac上运行/测试(Apple Inc. build 5659)

答案 5 :(得分:0)

您可以在结构中添加一个字段,指示哪个联合成员当前有效。一个简单的例子:

union int_or_float
{
    int int_member;
    float float_member;
};

struct node 
{
    union int_or_float data;
    bool int_is_valid;
    struct node *next;
};

(假设您有#include <stdbool.h>。)

请注意,完全取决于您保持int_is_valid成员的值与您存储的最后一个值一致,并仅在int_member为真时检索int_is_valid并检索仅当float_member为假时才int_is_valid

在实践中,使用enum而不是bool会更清楚。

答案 6 :(得分:-1)

你可能最好同时存储一个float和一个int,然后使用赋值函数将两者都设置为正确的值。一个类可能更适合这个

struct node 
{
    int idata;
    float fdata;
    struct node *next;
    void setData(int data);  
    void setData(float data);
};

node::setData(int data)
{
    idata = data;
    fdata = (float)data;
}

node::setData(float data)
{
    idata = (int)data;
    fdata = data;
}