【问题标题】:How to use Union in C language如何在C语言中使用Union
【发布时间】:2011-04-30 14:40:14
【问题描述】:

我有一个关于 C 语言联合的问题。 在联合中声明的变量将共享相同的内存,好的,我明白了。 例如,

union student {
   int i;
   int j;
}x;

我们如何访问 i 和 j? 如果我们有: x.i = 1; 然后我们printf("%d",j); 会发生什么?编译器错误? 好的,那么下面的情况呢:

union student {
       int i;
       float j;
    }x;

如果我们分配 x.i = 2; x.j 的值是多少?

【问题讨论】:

  • 不,它不会编译,除非你的意思是print("%s", x.j);
  • @ratzip 你为什么不自己试试呢? :)
  • @fardjad,我试过了,但我不知道联合是如何工作的!
  • @fardjad:对于一种像 C 一样有很多陷阱的语言,通过实验来学习语言的局限性和语义并不是一个好方法。
  • @ratzip,我的回答也解决了您的更新问题。在某种程度上,我现在会更新更多细节。

标签: c unions


【解决方案1】:

假设你使用

printf("%d", x.j); 

您将看到分配给x.i 的相同值,因为这两个变量占用相同的内存区域。像您所做的那样使两个变量都具有相同类型是不典型的。更典型的是,您会这样做,以便您可以查看相同的数据,但可以查看不同的数据类型。

例如,假设您想将 double 都视为 double 并且有时直接访问表示双精度的位(1 和 0),您可以使用以下联合来实现。

union DoubleData
{
    double d;
    char b[8];
} x;

现在您可以通过d 成员直接分配/访问双精度,或通过代表内存中双精度的 8 个字节操作相同的值。

使用您最近对该问题的更新,

union student 
{       
  int i;
  float j;    
}x;

让我们假设您的平台,int 是 4 个字节,float 是 4 个字节。在这种情况下,当您访问x.j 时,您将操纵这 4 个字节并将其视为一个双精度字节,当您访问 x.i 时,您将操纵这四个字节并将其视为一个整数。

所以两个变量都覆盖在同一个内存区域中,但不同的是您如何解释该内存区域中的位模式。请记住,任何 4 字节位模式都是有效的 int,但不是任何 4 字节位模式都是有效的浮点数。

让我们对您的平台做另一个假设,int 是 2 个字节,float 是 4 个字节。在这种情况下,当您访问 x.i 时,您将只处理被浮点数覆盖的一半位模式,因为在这种情况下,x.i 只会部分覆盖 x.j,因为 x.j 覆盖更多字节。

【讨论】:

  • 并且要小心,因为这是否安全取决于实现;实际上,它是语言中的 UB。
  • 你忘了尾随'f':printf("%d", x.j);
【解决方案2】:

ij 将共享相同的内存,因此您分配给其中的任何内容也将在其他成员中可用。

x.i  = 1;
// x.j = 1

【讨论】:

    【解决方案3】:

    这是“未定义的行为”。

    您不能先写信给i,然后再读j。您一次只能“使用”其中一个元素。

    【讨论】:

    • 有时您需要使用特定于实现的细节。仅仅因为它不是可移植的 C 并不意味着它应该被扔进外面的黑暗中。
    • @David:我很高兴看到“需要”在union 中写入int,并在同一union 中从不同的int 读取。跨度>
    • 没有必要。有时它只是方便。别担心,我只是在进行我自己的个人战斗,以捍卫特定于实现的非便携式 C。;-)
    猜你喜欢
    • 1970-01-01
    • 2013-09-27
    • 2011-07-04
    • 2019-01-27
    • 2020-08-16
    • 1970-01-01
    • 2016-03-23
    • 1970-01-01
    • 2020-04-28
    相关资源
    最近更新 更多