繁体   English   中英

C ++中的位移

[英]Bit shifting in C++

我有以下结构:

struct SysData
{ 
        // Topic (32 bits)
        UTL_UINT16_Tdef SystemID:11;    // set to decimal 25
        UTL_UINT16_Tdef TypeID:5;       // set to 2 (telemetry type)
        UTL_UINT16_Tdef ContentID;      // set to decimal 1234
}

SysData MsgHdr;
MsgHdr.SystemID   = 25;
MsgHdr.TypeID     = 2;
MsgHdr.ContentID  = 0;

如果我做这样的事情:

    unsigned int a;
    memcpy(&a, &MsgHdr, sizeof(MsgHdr));
    headerInfo[0] = a & 0x7FF;
    headerInfo[1] = (a >> 16) & 31;
    headerInfo[2] = (a >> 21) & 0xFFFF;

headerInfo [0]应该具有值25,但它有36.我做错了什么?

您不应该猜测SysData的内部表示。编译器可能选择将位字段打包在一起或不打包,将它们左右对齐等。它甚至可以选择将它们映射到32位整数以解决性能问题。 你只是不知道。 位域的未使用部分可能包含垃圾,它可能就在你获得36的位置。

这很奇怪,但不是很难检查。 将您的25改为其他值,看看你得到了什么。

但是,将结构存储到某些unsigned int可能不是一个好主意。 你为什么不直接访问bitfield? 就像在headerInfo[0] = MsgHdr.SystemID; 这就是bitfields的用途。 在你的例子中,memcopy只是一个时间的损失(也是危险的,你可以看到)。

未定义位域的实现,并根据您使用的编译器而有所不同。

(编辑:忽略我对36来自哪里的错误猜测)

我想不出你会如何达到36,但是对于bitfields,我强烈建议使用普通读取访问函数来读取它们,而不是将它们移动,即

SysData *pSysData = (SysData *) &MsgHdr;
headerInfo[0] = pSysData->ContentID;

顺便说一句,我不明白你的例子。 你说headerInfo [0]应该是25.但不应该是0吗? 你的例子说ContentID是0,我想你正在尝试阅读那里。

除了可能的endian问题或打包问题之外,headerInfo [1]的转换不应该是11而headerInfo [2]应该是16吗?

像EboMike一样,无法想象你得到的地方36

a)十进制25 = 00000011001 b)十进制2 = 00010 c)十进制1234 = 000010011010010

所以不同的组合是:

  • abc = 0000001 [100100] 010000010011010010
  • acb = 0000001 [100100] 00100110 [100100] 0010
  • bac = 000100000001 [100100] 0010011010010
  • bca = 0001000001001101001000000011001
  • cab = 0000100110 [100100] 000001 [100100] 010
  • cba = 0000100110 [100100] 001000000011001

在所需的100100位序列中没有任何结束,所以除非结构实际上存储在两个uint之外或者某些古怪的东西正在发生,否则我迷失了。 加载到调试器中,看看实际存储的内容。

如果我这样做:

#include <stdio.h>
#include <memory.h>

typedef unsigned short UTL_UINT16_Tdef;

struct SysData { 
  // Topic (32 bits)
  UTL_UINT16_Tdef SystemID:11;    // set to decimal 25
  UTL_UINT16_Tdef TypeID:5;       // set to 2 (telemetry type)
  UTL_UINT16_Tdef ContentID;      // set to decimal 1234
};

int main() {

  SysData MsgHdr;

  MsgHdr.SystemID   = 33;
  MsgHdr.TypeID     = 22;
  MsgHdr.ContentID  = 11;

  unsigned int a;
  memcpy(&a, &MsgHdr, sizeof(MsgHdr));

/*
  headerInfo[0] = a & 0x7FF;
  headerInfo[1] = (a >> 16) & 31;
  headerInfo[2] = (a >> 21) & 0xFFFF;
*/

  printf( "%08X %i\n", a, sizeof(SysData) );

  printf( "0: %i\n", a & 0x7FF );
  printf( "1: %i\n", (a >> 11) & 31 );
  printf( "2: %i\n", (a >> 16) & 0xFFFF );

}

我得到了预期的结果,而且键盘也是如此 - http://codepad.org/XNm0Yp90

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM