联盟与结构有何不同?其他语言有类似的结构吗?

Saj*_*ani 3 c c++ python java programming-languages

可能重复:
C中结构和联合之间的差异

我在C中看到了这个代码用于联合:

    union time
    {
      long simpleDate;
      double perciseDate;
    } mytime;
Run Code Online (Sandbox Code Playgroud)

联合和C中的结构有什么区别?你会在哪里使用工会,它有什么好处?Java,C++和/或Python中是否有类似的构造?

unw*_*ind 14

联合的行为就好像它的所有成员都在内存中的相同位置,重叠.

当您想要表示某种"通用"值或可以是任何一组类型的值时,这非常有用.由于字段重叠,因此只有在您知道之前已初始化字段时,才能合法访问该字段.尽管如此,由于C不会检查这一点,并且许多编译器会发出允许它的代码,因此这是一个常见的技巧...有趣的类型转换,例如:

union {
 int integer;
 float real;
} convert;

convert.real = 3.14;
printf("The float %f interpreted as an integer is %08x", convert.real, convert.integer);
Run Code Online (Sandbox Code Playgroud)

对于更加完善的用法,您可以跟踪最后存储在union中的内容,它可以查找如下所示:

typedef enum { INTEGER = 0, REAL, BOOLEAN, STRING } ValueType;

typedef struct {
  ValueType type;
  union {
  int integer;
  float real;
  char boolean;
  char *string;
  } x;
} Value;
Run Code Online (Sandbox Code Playgroud)

在这里,请注意联合实际上是周围结构中的一个字段Value.访问可能如下所示:

void value_set_integer(Value *value, int x)
{
  value->type = INTEGER;
  value->x.integer = x;
}
Run Code Online (Sandbox Code Playgroud)

这记录了union的当前内容是一个整数,并存储给定的值.例如打印a的功能Value可以检查type成员,并做正确的事情:

void value_print(const Value *value)
{
  switch(value->type)
  {
  case INTEGER:
    printf("%d\n", value->x.integer);
    break;
  case REAL:
    printf("%g\n", value->x.real);
    break;
  /* ... and so on ... */
  }
}
Run Code Online (Sandbox Code Playgroud)

Java中没有等价物.C++几乎是C的超集,具有相同的功能.它甚至"one-ups"C的实施,并允许匿名工会.在C++中,上面的内容可能没有命名内部union(x),这会使代码缩短很多.


Dou*_* T. 11

所以在你的例子中,当我分配时间时:

int main()
{
    time t;
}
Run Code Online (Sandbox Code Playgroud)

编译器可以解释&t中的内存,就好像它是一个long:

t.simpleDate;
Run Code Online (Sandbox Code Playgroud)

或者好像是双重的:

t.perciseDate;
Run Code Online (Sandbox Code Playgroud)

所以如果t的内存的原始十六进制看起来像

0x12345678;
Run Code Online (Sandbox Code Playgroud)

该值可以"解析"为double或long,具体取决于其访问方式.因此,为了使它有用,您必须知道如何将long和double打包并准确地在内存中进行格式化.例如,long将是一个2-s补码有符号整数,您可以在这里阅读.你可以在这里学习如何用二进制格式化double .

但是,结构只是将单独的变量分组,将不同的地址间隔分组到一个内存块中.

(注意你的例子可能很危险,因为sizeof(long)可能是32位而sizeof(double)总是64位)

当您需要"原始"表示(如char数组)和"消息"表示时,通常会使用联合.例如,要通过套接字发送的消息:

struct Msg
{
   int msgType;
   double Val1;
   double Val2;
}; // assuming packing on 32-bit boundary

union
{
   Msg msg;
   unsigned char msgAsBinary[20];
};
Run Code Online (Sandbox Code Playgroud)

希望有所帮助.

  • "为了它有用你必须知道如何打包和格式化长和双".工会的一种用途,不是标准所保证的,而是由大多数编译器保证的,是写一个成员然后读回另一个成员来获得一种重新解释.对于此用途,您需要知道存储表示.但是,还有另一个(最初用途)用途,即存储任何成员,记住您存储的内容,并回读同一成员.目的是在您不需要同时保存内存时节省内存.为此,格式无关紧要. (7认同)