gpt4 book ai didi

c++ - 如何使用结构和位域来确保精确的位顺序

转载 作者:行者123 更新时间:2023-11-28 02:10:55 25 4
gpt4 key购买 nike

我一直在搜索这个主题,我希望最终能在这里找到答案。

我想为特定硬件使用一个结构,我想在 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,我还想在带有 AVR 的 Atmel studio 7 中使用此代码。顺便说一下,我还使用了 #pragma pack(1)__attribute__((__packed__)) 并得到了 sizeof(packet) 相等到 35。

最佳答案

您有 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

该值将包含在两个字节 xxx00100110111xx 中,可以通过将两个字节移位和组合来重构它,如下所示:

xxx00100          << 8 AND
110111xx
xxx00100110111xx

然后将其左移 3 以从前一个字段中删除前 3 位,然后将其右移 3 + 2 以从下一个字段中删除最后 2 位,您将得到 0000000100110111 简而言之就是该字段的值。

写入字段的过程是相似的,但是,请确保您没有破坏相邻字段中的位 - 您需要保存并在为目标字段写入字节时正确恢复这些位。

关于c++ - 如何使用结构和位域来确保精确的位顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35706485/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com