【问题标题】:c union and bitfieldsc 联合和位域
【发布时间】:2010-06-21 17:47:33
【问题描述】:

位域可以在联合中使用吗?

【问题讨论】:

  • 做两件恶事时,是相加还是相乘? ;-)
  • +1 到 Amardeep。不要也不要 divya。
  • 较近的位域和联合一定是邪恶的。我在联合中使用结构来解析嵌入式软件中的字节输入/输出。它的舒适性超过了它的缺点。

标签: c bit-fields unions


【解决方案1】:

是的,他们可以。为什么不?联合中的位域的行为方式与它们在其他任何地方的行为方式相同。联合中的位域(或带有位域的联合)没有什么特别之处。

【讨论】:

    【解决方案2】:

    是的,这是可能的,但我建议不要这样做。位域的长度和打包是不可移植的。联合体的规模将难以预测(参见here)。当您使用联合或位域时,您会在代码中引入一定程度的复杂性。虽然这种复杂性在您的代码中可能是可以接受的,但将两者结合起来可能会导致无法接受的复杂性。如果您使用联合、结构和位域,则会遇到内存对齐问题。

    如果这是只需要在一台机器上构建和运行的一次性代码,那么它可能没问题。但是,如果您将其签入到版本控制中,它将永远存在,我建议您不要这样做。

    如果您举例说明为什么要这样做,我或其他人可以提出更好的替代方案。

    编辑:根据 cmets 进行澄清并征求反馈意见。

    【讨论】:

    • 与一般的位域相比,联合中的位域有哪些不可移植的地方?具体是什么将难以预测?
    • 您链接的帖子中的投诉是关于 sizeof() 一个包含位域的联合,而不是行为。结构大小始终取决于实现,与位域无关。还有人抱怨无法获取位域成员的地址,但这只是位域的工作方式,与联合无关。
    • 更新得不那么模糊了。一般来说,我对大小/内存对齐非常偏执,因为我致力于微控制器的固件。未对齐的结构或变量会影响性能,并可能导致非原子加载和存储。您的里程可能会有所不同。
    • 但这基本上意味着您通常不喜欢位域。与原始问题没有直接关系。
    • @AndreyT 大多数情况下,是的。我确实认为工会使问题更加复杂,因为工会的每个成员都导致了如何确定工会规模的复杂性。我正在阅读它,因为我已经看到在您将协议映射到 c-struct 的情况下使用它,并且错误预测对齐会导致错误。在您认为含糊或误导的编辑之后,我的回答是否仍然存在?
    【解决方案3】:

    如果您考虑一下 union 的工作原理,您会有答案,当然是肯定的(为什么不)?正如我们所期望的,联合大到足以容纳最大的基准,因此自然而然地就更小了。位域被打包到“容器”中,编译器必须能够评估它们的最终实际大小。下面展示了一些有趣的事实(当然是联合的错误用法,但不是针对位域的存在!)

    #include <stdio.h>
    
    union test {
      int a:5;
      int b:12;
      float c;
      double d;
      int x;
    };
    
    int main()
    {
      union test x;
      printf("%d\n", sizeof(x));
      x.a = 31;
      printf("%d\n", x.a);
      printf("%d\n", x.b);
      x.c = 1.23;
      printf("%d\n", x.a);
      printf("%f\n", x.c);
      x.x = 31;
      printf("%d\n", x.x);
      printf("%d\n", x.a);
      printf("%d\n", x.b);
    }
    

    【讨论】:

      【解决方案4】:

      只有写入一个联合元素并从另一个联合元素读取,这才是不安全的。如果您的实现细节确保不会发生这种情况,那么包含 bitfied(可能还有其他成员)的联合具有定义明确的安全行为。

      【讨论】:

      • 这不是 C++:通过联合的类型双关语在 C 中完全有效,其行为方式与 C++ 的 reinterpret_cast 类似。技术勘误 3 清楚地说明了这一点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-09
      • 1970-01-01
      • 1970-01-01
      • 2012-09-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多