将位字段转换为int

Sha*_*rtz 14 c bit-fields

我有这样声明的位字段:

typedef struct morder {
    unsigned int targetRegister : 3;
    unsigned int targetMethodOfAddressing : 3;
    unsigned int originRegister : 3;
    unsigned int originMethodOfAddressing : 3;
    unsigned int oCode : 4;
} bitset;
Run Code Online (Sandbox Code Playgroud)

我也有int数组,我想从这个数组得到int值,它表示这个位字段的实际值(实际上是某种机器字,我有它的部分,我想要int表示整个字).

非常感谢.

JXG*_*JXG 21

拜托,拜托,千万不能用一个联盟.或者,更确切地说,通过使用联合来理解你正在做什么 - 最好在使用之前.

正如您在本回答中所看到的,不要依赖位域来移植.特别针对您的情况,结构中位域的排序依赖于实现.

现在,如果您的问题是,如何将bitfield结构打印为int,偶尔进行私人审核,当然,工会很棒.但是你似乎想要你的位域的"实际价值".

所以:如果你只使用这一台机器/编译器组合,并且你不需要依赖 int的数学值,只要它有意义,你就可以使用联合.但是如果您可能移植代码,或者您需要int的"实际值",则需要编写位操作代码以将位字段转换为正确的int位.

  • 结构中位域的+1'排序是依赖于实现的 (10认同)
  • @mahesh,不一定。排序是依赖于实现的,所以编译器真的可以为所欲为。排序可能没有数学意义。联合将为您提供从位域到整数的一致映射,但您事先不知道这些整数是否是数学值。如果你移植你的代码,每个映射都可能不同。 (2认同)
  • @Mahesh 还值得注意的是,读取最近未写入的联合成员是未定义的行为。我认为大多数编译器会做你想做的事,但要记住一些事情。 (2认同)

str*_*ger 16

你可以使用一个联盟:

typedef union bitsetConvertor {
    bitset bs;
    uint16_t i;
} bitsetConvertor;

bitsetConvertor convertor;
convertor.i = myInt;
bitset bs = convertor.bs;
Run Code Online (Sandbox Code Playgroud)

或者您可以使用演员:

bitset bs = *(bitset *)&myInt;
Run Code Online (Sandbox Code Playgroud)

或者您可以在联合中使用匿名结构:

typedef union morder {
    struct {
        unsigned int targetRegister : 3;
        unsigned int targetMethodOfAddressing : 3;
        unsigned int originRegister : 3;
        unsigned int originMethodOfAddressing : 3;
        unsigned int oCode : 4;
    };

    uint16_t intRepresentation;
} bitset;

bitset bs;
bs.intRepresentation = myInt;
Run Code Online (Sandbox Code Playgroud)

  • 被否决:`bitset bs = *(bitset *)&myInt;` 是打破*严格别名规则*的典型例子。 (9认同)
  • `uint16_t` 不能保证为 `unsigned int`。联合取决于实现细节;位域结构对其布局几乎没有任何保证。强制转换违反了 _effective type_(又名严格别名)规则 -> 未定义的行为。不好的做法。 (4认同)