在C++中使用按位数据的结构

Joe*_* M. 7 c++ struct bit-manipulation

可能重复:
将位字段转换为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;
};
Run Code Online (Sandbox Code Playgroud)

即该结构包含一个16位变量,该变量作为一些较小的(在某些情况下,1位标志)块处理.

我的问题是,是否有一种简单的方法可以将整个16位字作为一个值处理,比如将其输出到控制台或文件,或将其添加到另一个数据结构?除了移动单个结构元素并将它们添加到临时uint16_t变量之外,我不知道这样做的任何方法.似乎可能有一种更简单的方法来提取整个单词,但我找不到有关编译器如何处理这样的结构的任何信息.

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

Kir*_*lev 10

这里的标准方法是使用匿名结构/联合,如下所示:

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;
};
Run Code Online (Sandbox Code Playgroud)

或者,如果联盟不是顶级对象,

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;
   };
};
Run Code Online (Sandbox Code Playgroud)

此定义允许直接访问内部字段,例如:

mystruct s1;
s1.WordCntErr = 1;
Run Code Online (Sandbox Code Playgroud)

严格地说,编译器没有对联盟的不同成员如何相互重叠提供任何保证.它可以使用不同的对齐甚至移位.这里的很多人都会轻易指出这一点.然而,从实际角度来看,如果联盟的所有字段具有相同的大小,您可以安全地假设它们占用相同的内存.例如,代码

s1.word_field = 0;
Run Code Online (Sandbox Code Playgroud)

将所有位字段清零.大量的代码正在使用它.永远不会停止工作是不可想象的.

  • 如果您写入联合的一个字段然后从另一个字段读取,则会产生未定义的行为. (5认同)