[英]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
所以不同的组合是:
在所需的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.