在C逐位数据++结构[重复](Structures with bitwise data in C++

2019-07-31 17:00发布

可能重复:
转换位字段为int

我工作的一个应用程序,其中一部分的处理包含了许多的1位标志16位字。 我使用类似下面所示的一个结构处理数据:

struct mystruct
{
   uint16_t Reserved1   :3;
   uint16_t WordErr     :1;
   uint16_t SyncErr     :1;
   uint16_t WordCntErr  :1;
   uint16_t Reserved2   :10;
};

即,结构包含作为多个较小的(在某些情况下,1比特的标记)片处理的单个16位变量中。

我的问题是这样的,有一个简单的方法来处理整个16位字为一个值,比如说,将其输出到控制台或文件,或将其添加到另一个数据结构? 我不知道这样做除了转移的具体的结构元素,并将它们添加到一个临时uint16_t变量的任何方式。 看来,有可能是提取整个字的简单的方法,但我不能找到编译器如何处理的结构是这样的任何信息。

编辑:我想这可能是显而易见的,但我试图简而言之做的是能够单独访问1位标志,以及使用结构类型uint16_t的一个变量(即无符号短,16位)。

Answer 1:

这里的标准方法是使用匿名结构/联合,这样的:

union mystruct
{
   struct
   {
      uint16_t Reserved1   :3;
      uint16_t WordErr     :1;
      uint16_t SyncErr     :1;
      uint16_t WordCntErr  :1;
      uint16_t Reserved2   :10;
   };

   uint16_t word_field;
};

或者,如果工会不作为好一个顶级对象,

struct mystruct
{
   union
   {
       struct
       {
          uint16_t Reserved1   :3;
          uint16_t WordErr     :1;
          uint16_t SyncErr     :1;
          uint16_t WordCntErr  :1;
          uint16_t Reserved2   :10;
       };

       uint16_t word_field;
   };
};

该定义允许到内部领域,如直接访问:

mystruct s1;
s1.WordCntErr = 1;

严格地说,编译器不给就如何工会的不同成员将互相重叠的任何担保。 它可以使用不同的路线,甚至转变。 很多人在这里会很容易地指出这一点。 然而,从实用的角度来看看这个,如果工会的各个领域具有相同的大小,你可以安全地假设,他们占据了同一块内存。 例如,代码

s1.word_field = 0;

将归零所有位字段。 代码吨都采用这种。 这是不可想象的,这将不会停止工作。



Answer 2:

简单的答案是,你不能做到这一点。 较长的答案是,你可以做到这一点,但在细节上取决于你的编译器。 这种特殊的位字段布局看起来很像它应该映射到硬件寄存器,在这种情况下,你已经有了编译器的依赖关系:对位字段是如何安排的细节是实现定义的。 所以,当你保证自己的编译器勾画出来你所期望的方式,你也可以检查它是否支持通过联合类型的双关语。 虽然写入工会的一个领域,从另一个读正式产生不确定的行为,无论是在C和C ++中,大多数(全部?)编译器都支持它在简单的情况是这样的。



Answer 3:

是来自工会技术的未定义行为的替代,你可以复制的数据:

mystruct m;
m.Reserved1 = 0;
m.WordErr = 1;
m.SyncErr = 0;
m.WordCntErr = 0;
m.Reserved2 = 0;

uint16_t value = 0;
memcpy(&value, &m, sizeof(value));

[码]

当然,输出/端敏感的特定于平台的,所以如果你打算写出来,所以你可以读一遍,然后在考虑到这一点。



Answer 4:

这是一个什么样的工会是。 我很少需要使用一次,所以我的语法可能会生锈,但是它看起来是这样的:

union myunion
{
    struct mystruct
    {
       uint16_t Reserved1   :3;
       uint16_t WordErr     :1;
       uint16_t SyncErr     :1;
       uint16_t WordCntErr  :1;
       uint16_t Reserved2   :10;
    };
    uint16_t word;
};

当然,这增加了打字,只要你访问它,所以你可能想只是尝试类型转换,如果你只需要偶尔。



文章来源: Structures with bitwise data in C++ [duplicate]