【问题标题】:convert byte array to a pointer with problem of endian将字节数组转换为有字节序问题的指针
【发布时间】:2020-02-06 07:49:06
【问题描述】:

我应该从 pcap 文件中读取数据到数组中,然后将其转换为结构指针。

还有字节序的问题。

这是我的代码

#include "stdio.h"

#pragma pack(1)
struct header
{
    unsigned char len:4;
    unsigned char version:4;

    unsigned short pkg_len;
    unsigned short pkg_flag;
};

int main()
{
    // assume i read 5 bytes from  a file into array a.
    unsigned char a [] = {0x45, 0xff, 0x08, 0xee, 0x09};
    header *i = (header *)&a;

    printf("%02hx %02hx %02hx %02hx\n", i->version, i->len, i->pkg_len, i->pkg_flag);
    return 0;
}

打印出来了:

 04 05 08ff 09ee

但是,我想要的是:

04 05 ff08 ee09

我该怎么办?非常感谢!

【问题讨论】:

  • 你真正的问题是什么?为什么不能像header i[]={{4,5,0xff08,0xee09}} 那样做?
  • 不保证位域的顺序。您最好使用手动位移,这样您就可以更好地控制使用哪些位以及如何使用。此外,%x 需要 unsigned int 作为默认输入,因此在将值传递给 printf 时需要转换它们。对于unsigned short 字段,您可以使用%hx 而不进行强制转换。
  • 因为数组 a 是从无法更改的文件中读取的。我能做的就是将它读入一个数组并将其转换为一个结构指针。
  • 可以修改header结构中的字段顺序吗? short 字段的字节顺序可以用htons 解决,但是没有内置函数可以在单个字节内交换顺序。无论如何,这将是很多实现和设备特定的,所以不要指望任何可移植性。

标签: c++ arrays pointers type-conversion endianness


【解决方案1】:

x86 使用 little-endian 字节顺序。所以,你得到正确的结果。 如果你想得到高端结果(恕我直言,你想要那个),你可以用'htons'函数改变每个字段:它将主机顺序更改为网络(高端)顺序。

【讨论】:

    【解决方案2】:

    谢谢大家。

    最后的代码是这样的:

    #include "stdio.h"
    
    #define _UNIX
    //#define WIN32
    
    #ifdef _UNIX
    #include <arpa/inet.h>
    #endif
    #ifdef WIN32
    #include <windows.h>
    #pragma comment(lib,"ws2_32.lib")
    #endif
    
    const int data4test = 1;
    #define is_bigendian() ((*(char *)&data4test) == 0 )
    
    
    #pragma pack(1)
    struct ip_header
    {
        unsigned char len:4;
        unsigned char version:4;
    
        unsigned short pkg_len;
        unsigned short pkg_flag;
    };
    
    int main()
    {
        if (is_bigendian())
            printf("big endian \n");
        else
            printf("little endian \n");
    
        unsigned char a [] = {0x45, 0xff, 0x08, 0xee, 0x09};
        ip_header *i = (ip_header *)&a;
    
        printf("%02hx %02hx %04hx %04hx\n", i->version, i->len, htons(i->pkg_len), htons(i->pkg_flag));
        return 0;
    }
    

    我还没有找到更好的方法来解决这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-22
      • 2017-09-21
      • 2012-02-24
      • 2013-02-13
      相关资源
      最近更新 更多