0

我正在尝试读取从网络接收到的一系列位(以预定义的格式)并且想知道我们是否必须照顾字节序。

例如,预定义的格式表示从最高有效位开始接收的数据将如下所示

 |R||  11 bits data||20 bits data||16 bits data| where R is reserved and ignored.

我的问题是在提取时我必须照顾字节序还是我可以这样做

u16 first_11_bits = *(u16 *)data & 0x7FF0) >>4
u32 20_bits_data  = *(u32 *)data & 0x000FFFFF)
4

3 回答 3

1

什么样的网络?IP 是按字节定义的,因此无论位流在底层中的顺序如何,都已从您那里抽象出来,并且您按照 CPU 理解它们的顺序接收这些位。这意味着 C 为您提供访问这些位的抽象是可移植的。在 C 中考虑左移或右移。无论 CPU 中的字节序是什么,在 C 中移动的方向和语义都不会改变。

那么问题来了:数据是如何被另一端编码成字节流的呢?但是,另一端对数据进行编码应该是您对其进行解码的方式。如果他们只是将比特塞入一个字节并通过网络发送该字节,那么您无需关心。如果他们将位放入一个 int16,然后以网络字节顺序发送,那么您需要担心该 int16 的字节顺序。如果他们将这些位放入 int32 并发送,那么您需要担心该 int32 的字节顺序。

于 2013-09-30T12:43:22.717 回答
0
u16 first_11_bits = *(u16 *)data & 0x7FF0) >>4
u32 20_bits_data  = *(u32 *)data & 0x000FFFFF)

这是UB。要么data指向 a要么指向u16a u32。它不能指向两者。这不是字节顺序问题,只是无效访问。您必须通过与写入访问相同的指针类型进行读取访问。无论您以哪种方式编写它,这就是您阅读它的方式。然后你可以对你读回的值进行位操作,这将与你写入的值相同。

这可能出错的一种方法是编译器可以自由假设通过 a 写入u32 *不会影响通过 a 读取的值u16 *。所以写入可能是内存,但读取可能来自缓存在寄存器中的值。这破坏了现实世界的代码。

例如:

u16 i = * (u16 *) data;
* (u32 *) data = 0;
u16 j = * (u16 *) data;

编译器可以自由地将最后一行视为u16 j = i;. 它最后i以相同的方式读取,并且可以自由假设对 a 的写入u32 *不会影响从 a 读取的结果u16 *

于 2013-09-30T12:22:18.047 回答
0

是的,在读取/写入外部资源(文件、网络等)时,您总是需要担心字节顺序。但这与位操作无关。

直接铸造(u16 *)data不是可移植的做事方式。

我建议在进行位操作之前使用将数据转换为本机类型的函数。

于 2013-09-30T12:26:32.453 回答