5

我正在尝试解码从大端机器发送到解码器的一些数据,该解码器位于小端机器上。我没有经常处理这个问题,我觉得我自己很困惑。

我使用位集来打印我的数据,这样我就可以准确地看到它是如何针对特定的 32 位结构输出的,并且我可以看到我需要的数据位于位序列的中间。

现在,我知道如果你有一个 32 位的值,从大到小,你颠倒了字节顺序。如果我这样做,我的数字就不会像我期望的那样结束(手工完成)。

所以,例如。我有一个 32 位无符号整数。我知道它来自我的 Big-Endian 机器,为 0x50000000。当我在 little-endian 机器上使用 bitset 打印它时,cout << "packSpare 32: " << bitset<32>(Data.pack_Spare).to_string() << endl; 我得到 0x00005000。所以它看起来更像是按顺序交换了前两个字节,然后按顺序交换了后两个字节。

我最初有一个这样的结构:

#pragma pack(push, 1)
    struct PACK_SPARE
    {
        int         Spare3:28;
        int         Heading_Reference:1;
        int         Spare2:1;
        int         H_Valid:1;
        int         Spare5:1;
    };
    #pragma pack(pop)

这是从大端机器发送它的相反顺序,但我注意到关于发生一些明显的位交换的问题,所以我想把整个东西拉成 32 位,然后交换,然后打印数据。现在我只是在使用int pack_Spare;

它只是取两个 16 位块并交换它们,而不是对整个 32 位值进行交换吗?对不起,如果这没有意义,就像我说的那样,我有点困惑。

编辑 此数据不是来自网络。我正在从视频文件中流式传输位。我将此数据存储到其相应的值中。所以我想我的问题是如果我有一个 32 位 int,然后将数据读取到该变量中,如果我使用 bitset,为什么它交换我的 32 位 int 的两个 16 位分组,而不是按字节进行?我期待 0x50000000,但我得到 0x00005000(交换了 0000 和 5000,而不是我所期望的典型的字节序交换,它颠倒了所有字节的顺序)。

4

4 回答 4

5

只需使用hton()和合作。用于在网络和本机字节顺序之间进行转换,然后应用真正的按位算术运算,例如移位和屏蔽。你不需要搞乱即时内存访问。

于 2013-10-25T20:24:23.393 回答
4

您需要在发送时转换为网络字节顺序(使用htonX()),然后在读取时将其转换回来(使用ntohX())。

注意:提供的链接适用于 Windows 版本的函数。不过,POSIX 系统具有类似的签名。

于 2013-10-25T20:26:27.853 回答
2

虽然除了介绍之外我不经常推荐维基百科,但我确实在这里找到了一个很好的字节序讨论,(回答你的问题为什么它交换我的 32 位 int 的两个 16 位分组,而不是按字节进行? )。

讨论发生在该链接页面下方约 2/3 处...查找此内容:

在此处输入图像描述

在同一页面上有几个关于字节序的有趣的事情。

于 2013-10-25T21:10:35.840 回答
0

我用来重新安排事情的一种方法是使用联合。我是 Endianings 的新手,但很快我就知道了我需要什么,我想出的最快方法(我相信,CPU 密集度较低)是使用以下代码:

template <class T, const int size = sizeof (T)>
class cTypeConvert final
{
    public:
        union
        {
            T val;
            char c [size];
        }uTC;
};

在我的情况下,使用chars 字符串,我只需要将cTypeConvert::uTC.c[]数组从sizeto0输入并读取为我实例化此模板的类型。最好的部分是我可以将它用于我可能需要的任何标准类型,并且它总是可以工作的。

请注意,如果您必须在使用此模板之前将其类型转换为 char,那么您最终可能会比上述方法浪费更多的 CPU。

于 2015-02-22T12:30:50.467 回答