C ++中的位移

时间:2010-08-07 00:37:16

标签: 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.我做错了什么?

5 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分:0)

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

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

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

SysData *pSysData = (SysData *) &MsgHdr;
headerInfo[0] = pSysData->ContentID;
是的,我不明白你的例子。你说headerInfo [0]应该是25.但不应该是0吗?你的例子说ContentID是0,我想你正在尝试阅读那里。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

像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或者古怪的东西上,否则我迷失了。加载到调试器中,看看实际存储的内容。

答案 4 :(得分:0)

如果我这样做:

#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