17

我使用了具有这样结构的位字段,

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;

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

4

3 回答 3

37

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

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

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;
    };
};
于 2012-07-04T09:55:21.397 回答
10

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

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

于 2012-07-04T09:54:07.310 回答
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
于 2021-10-04T17:59:33.490 回答