我一直在搜索这个话题,我希望最终得到答案。
我想使用特定硬件的结构,我想在C中实现它;这是我想要的包:
typedef struct {
quint8 startByte :8;
quint16 ch1 :11;
quint16 ch2 :11;
quint16 ch3 :11;
quint16 ch4 :11;
quint16 ch5 :11;
quint16 ch6 :11;
quint16 ch7 :11;
quint16 ch8 :11;
quint16 ch9 :11;
quint16 ch10 :11;
quint16 ch11 :11;
quint16 ch12 :11;
quint16 ch13 :11;
quint16 ch14 :11;
quint16 ch15 :11;
quint16 ch16 :11;
quint8 endByte1 :8;
quint8 endByte :8;
}packet;
如果计算大小,则为25个字节。但是当我使用sizeof(packet)
时,我得到46。
现在我正在使用Qt 5.5,我也想在Atmel工作室7中使用此代码和AVR。
顺便说一下,我也使用了#pragma pack(1)
和__attribute__((__packed__))
,并使sizeof(packet)
等于35。
答案 0 :(得分:2)
你有16个短路* 2个字节= 32个字节+起始字节+两个结束字节 - 如果它是打包的,总共35个字节。由于您对11位字段使用16位数据类型,因此只剩下5个字节 - 您不能将11位字段装入5位,因此这5位基本上是浪费的。
0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
| field 1 |xxxxx| field 2 |xxxxx| field 3 |xxxxx
如果我理解正确,你想要达到的目标更像是:
0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
| field 1 | field 2 | field 3 | field 4 |...
我不确定编译器是否可以为您生成这样的布局,但是如评论中已经提到的那样,您可以手动执行此操作。编译器没有这样做,因为它效率很低 - 为了读取跨越边界的字段,你必须做两次读取,掩码,移位和组合最终结果。
我已经链接的答案详细解释了位操作,这里唯一不同的是你将跨越边界。
| byte1 | byte2 | byte3 | byte4 |
0123456701234567012345670123456701
| field 1 | field 2 | field 3 |
例如,您想要读取字段2 - 它的索引是1,因此1 * 11 = 11 - 这是字段的位偏移量。 11/8 = 1,余数为3.这意味着它的值在第二个字节的第3位之后开始,占据8-3 = 5位,11-5 =下一个字节的6位。我们假设字段值为00100110111
。
| byte1 | byte2 | byte3 | byte4 |
0123456701234567012345670123456701
| field 1 | field 2 | field 3 |
xxx00100110111xx
该值将包含在两个字节xxx00100
和110111xx
内,并且可以通过移动和组合这两个字段来重建它:
xxx00100 << 8 AND
110111xx
xxx00100110111xx
然后将其向左移3以切断前一个字段的前3位,然后将其右移3 + 2以切断下一个字段的最后2位,并留下0000000100110111
这是短期内该领域的价值。
为了编写字段,过程类似,但是,请确保不要破坏相邻字段中的位 - 您需要保存,然后在为目标字段写入字节时正确恢复这些位。 / p>