我有以下结构:
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.我做错了什么?
答案 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
所以不同的组合是:
在所需的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