【问题标题】:Is it valid to use bit fields with union?使用联合位域是否有效?
【发布时间】:2012-07-04 19:15:54
【问题描述】:

我用过这样结构的位域,

struct
{
       unsigned int is_static: 1;
       unsigned int is_extern: 1;
       unsigned int is_auto: 1;
} flags;

现在我想知道这是否可以通过联合来完成,所以我修改了代码,例如,

union
{
       unsigned int is_static: 1;
       unsigned int is_extern: 1;
       unsigned int is_auto: 1;
} flags;

我找到了具有联合工作的位字段,但是正如我从输出中所理解的那样,联合中的所有这些字段都被赋予了一个位。现在我看到使用联合位字段并没有错误,但在我看来,像这样使用它在操作上是不正确的。那么答案是什么 - 将位域与 union 一起使用是否有效?

【问题讨论】:

  • 请问,什么操作不正确?

标签: c structure bit-fields unions


【解决方案1】:

这是一个关于如何使用联合位域的示例。我还展示了如何安排 MSB。在图片中它看起来像这样:

 MSB        LSB
 7            0
+------+-------+
| five | three |
| bits | bits  |
+------+-------+

// A struct tag definition of 
// two bit fields in an 8-bit register
struct fields_tag {
   // LSB
   unsigned int five:5;
   unsigned int three:3;
   // MSB
};

// here is a tag and typedef for less typing
// to modify the 8-bit value as a whole
// and read in parts.
typedef union some_reg_tag {
    uint8_t raw;
    struct fields_tag fields;
} some_reg_t;

这里是如何在 Arduino 中使用位域

some_reg_t a_register;
a_register.raw = 0xC2;  // assign using raw field.

Serial.print("some reg = ");  // dump entire register
Serial.println(a_register.raw, HEX);   // dump register by field
Serial.print("some reg.three = ");
Serial.println(a_register.fields.three, HEX);
Serial.print("some reg.five = ");
Serial.println(a_register.fields.five, HEX);

这是显示结果的输出

some reg = C2
some reg.three = 6
some reg.five = 2

【讨论】:

    【解决方案2】:

    给你一把枪和子弹。可以用它来射击自己吗?当然不是,但如果你愿意,没有人可以阻止你这样做。

    我的观点是,就像枪和子弹一样,联合和位域是工具,它们有其目的、用途和“滥用”。因此,正如您在上面所写的那样,在联合中使用位域是完全有效的 C 语言,但却是一段无用的代码。 union 中的所有字段共享相同的内存,因此您提到的所有位域本质上都是相同的标志,因为它们共享相同的内存。

    【讨论】:

    • 这个比喻远比OP问题中的代码无用。
    • 如果位在不同时间表示不同的含义,则非常有用,例如微控制器上的硬件寄存器。这也经常出现在文件格式中,作为一种节省空间的方法,将不同类型的数据塞进一个数组中,并有一个标志来告知每个元素的类型。 SO 确实存在问题,人们认为他们知道应该如何使用语言功能,基于他们有限的个人经验。
    【解决方案3】:

    它是有效的,但正如你发现的那样,你在那里做的方式没有用。

    您可以这样做,这样您就可以使用标志同时重置所有位。

    union {
        struct {
            unsigned int is_static: 1;
            unsigned int is_extern: 1;
            unsigned int is_auto: 1;
        };
        unsigned int flags;
    };
    

    或者你可以这样做:

    union {
        struct {
            unsigned int is_static: 1;
            unsigned int is_extern: 1;
            unsigned int is_auto: 1;
        };
        struct {
            unsigned int is_ready: 1;
            unsigned int is_done: 1;
            unsigned int is_waiting: 1;
        };
    };
    

    【讨论】:

    • 假设您需要匿名结构,我添加了一些分号。另请注意,它们不是标准 C。在 gcc 中,您必须使用 -fms-extensions 才能使它们工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多