我正在尝试读取从网络接收的比特序列(以预定义的格式),并想知道我们是否必须照顾endianees。
例如,预定义的格式表示从最高有效位开始接收的数据将如下所示
|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)发布于 2013-09-30 20:43:23
什么样的网络?IP是以字节为单位定义的,所以无论比特流在底层中的顺序是什么,都已经从您那里抽象出来了,您可以按照CPU理解它们的顺序接收这些比特。这意味着C语言提供的访问这些位的抽象是可移植的。考虑在C中向左或向右移动,无论CPU中的字节顺序是什么,在C中移动的方向和语义都不会改变。
所以问题是:数据是如何被另一端编码成字节流的?然而,另一端编码的数据应该是您解码它的方式。如果它们只是将位推入一个字节并通过网络发送该字节,那么您就不需要关心了。如果他们将位放入一个int16中,然后以网络字节顺序发送它,那么您需要担心该int16的字节顺序。如果他们将比特放入int32中并发送,那么您需要担心该int32的字节顺序。
发布于 2013-09-30 20:22:18
u16 first_11_bits = *(u16 *)data & 0x7FF0) >>4
u32 20_bits_data = *(u32 *)data & 0x000FFFFF)这是UB。data要么指向u16,要么指向u32。它不能同时指向两个。这不是一个字节序问题,它只是一个无效的访问。必须通过与访问用于写入的指针类型相同的指针类型访问用于读取的指针。不管你用哪种方式写,你就是这样读它的。然后,您可以对读回的值执行位操作,该值将与您写入的值相同。
这可能会出错的一种方式是,编译器可以自由地假设通过u32 *进行的写入不会影响通过u16 *读取的值。因此,写入可以是对存储器的,但是读取可以是来自高速缓存在寄存器中的值。这破坏了现实世界的代码。
例如:
u16 i = * (u16 *) data;
* (u32 *) data = 0;
u16 j = * (u16 *) data;编译器可以自由地将最后一行视为u16 j = i;。它最后一次以完全相同的方式读取i,并且可以自由地假设对u32 *的写入不会影响从u16 *读取的结果。
发布于 2013-09-30 20:26:32
是的,在读/写外部资源(文件、网络等)时,您总是需要担心字节顺序问题。但它与位操作没有任何关系。
直接转换(u16 *)data不是一种可移植的方式。
我建议在进行位操作之前,使用函数将数据转换为本机类型。
https://stackoverflow.com/questions/19094073
复制相似问题