【问题标题】:Endianess inside a byte字节内的字节序
【发布时间】:2012-12-03 12:20:24
【问题描述】:

最近我正在追踪一个当网络通信的两端具有不同的字节序时出现的错误。一方已经发了一个电报标记lastSegment,而另一方还在无休止地等待最后一段。

我读了这段代码:

#ifndef kBigEndian
    struct tTelegram
    {
       u8 lastSegment : 1;
       u8 reserved: 7;
       u8 data[1];
    };
#else
    struct tTelegram
    {
       u8 reserved: 7;
       u8 lastSegment : 1;
       u8 data[1];
    };
#endif

我知道字节序与多字节类型有关,例如 int、long 等。但是为什么它在前面的代码中关心呢? lastSegmentreserved 在单个字节内。

这是一个错误吗?

【问题讨论】:

标签: c++ endianness


【解决方案1】:

你的结构中有 16 位。在 32 位或 64 位架构上,取决于字节序data 可能出现在“之前”reservedlastSegment,或者在查看原始数据时可能出现在“之后”二进制。 IE 如果我们考虑 32 位,您的结构可能会沿 32 位边界打包。它可能看起来像这样:

 padbyte1 padbyte2 data lastSegment+reserved

或者它可能看起来像这样

 lastSegment+reserved data padbyte1 padbyte2

因此,当您将这 16 位放在网络上,然后在另一端重新解释它们时,您知道您收到的是 data 还是 lastSegment

您的问题不在字节内,它的位置是 datareservedlastSegment 的关系。

【讨论】:

  • 所以我应该改变字节顺序 ifdef 的位置,以便 lastSegment+reserved 在大端中出现在 data 之前,在小端中出现在 data 之后。对吗?
  • @EricZ:不,如果您关心定义明确的数据格式,则应该完全避免使用位域。
【解决方案2】:

当涉及到位域时,甚至在同一 CPU 上运行的不同编译器之间也不能保证排序。 理论上你甚至可以通过使用相同的编译器更改标志来改变顺序(不过,公平地说,我必须补充一点,我实际上从未见过这种情况发生)。

【讨论】:

  • 那么当通过网络向对方传递一个字节时,不保证对方得到正确的值?
  • @EricZ:没错。或者更准确地说,真的没有没有一个“正确的价值”可以接受。
  • 另一方将获得与发送相同的字节...但接收字节的程序可能编译不同,因此它将结构的成员变量与发送的程序不同的位相关联字节,即使发送方和接收方使用相同的源代码,也会导致混淆/不兼容。如果您避免使用 C 的位域功能,而是使用自己的位打包逻辑(使用位移位和位与和位或)来打包/解包字节,则可以避免该特定问题。
  • 但是一般的网络协议是怎么工作的呢?例如,它通常只强制执行网络字节顺序。但是如何保证对方收到的数据和原方发来的数据一模一样呢?您通过 MSN 向您的朋友发送了一条消息,例如,他很可能会收到一条不同的消息?困惑。
  • @EricZ:至少如果您通过 TCP 发送,您几乎可以保证线路一端的内容与另一端的内容相匹配。问题完全在于您的 CPU 是如何被编程来解释这些位的。 Jeremy 是对的:避免这种情况的主要方法是自己管理位打包和解包。
猜你喜欢
  • 2019-09-24
  • 2010-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-27
  • 2022-01-22
相关资源
最近更新 更多