2

I should read data from a pcap file to an array, and then convert it to a struct pointer.

and there is a problem of endian.

there is my code

#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;
}

it printed :

 04 05 08ff 09ee

however, what i want is :

04 05 ff08 ee09

what should i do ? thank you very much!

4
  • What is your real problem? Why can't you just do it like header i[]={{4,5,0xff08,0xee09}}? Commented Feb 6, 2020 at 7:53
  • The order of bit fields is not guaranteed. You are better off using manual bit shifting so you are in more control which bits are used and how. Also, %x expects an unsigned int as input by default, so you need to cast your values when passing them to printf. In the case of the unsigned short fields, you can use %hx without casting. Commented Feb 6, 2020 at 8:01
  • because the array a was read from a file that can not change. what i can do is read it to an array and convert it to a struct pointer. Commented Feb 6, 2020 at 8:03
  • Can you modify the order of fields in header struct? Endianness of short fields may be solved with htons, but there's no built-in function to swap order within a single byte. Anyway, that would be a lot implementation and device specific, so don't expect any portability. Commented Feb 6, 2020 at 8:10

2 Answers 2

1

The x86 uses little-endian byte order. So, you get correct result. If you want to get high-endian result (imho, you want that), you might change each field with 'htons' function: it change host order to network (high-endian) order.

Sign up to request clarification or add additional context in comments.

Comments

1

thank you all.

the final code is like this:

#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;
}

I have not find a better way to resolve this problem.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.