C++ How can i fill the bit fields of a struct from a uchar array?

0

I have an unsigned char array with values as below:

u_char *t_header[4]; //filled with values 0x00000047,0x00000004,0x00000093,0x00000012

I have a struct as below:

            #pragma pack(push, 1)
            typedef struct th_struct {
                unsigned s_byte : 8;
                unsigned t_e_indicator : 1;
                unsigned p_u_s_indicator : 1;
                unsigned t_priority : 1;
                unsigned id : 13;
                unsigned t_s_control : 2;
                unsigned a_f_control : 2;
                unsigned c_counter : 4; 
            }th_struct;
            #pragma pack(pop)

I am trying to fill the struct fields as below:

            const struct  th_struct *tsh;
            tsh = (struct th_struct*)(t_header);

It fills the tsh->s_byte with 71 = 0x47 in hex as expected but the rest of the fields are all 0.

What i have to do to fill struct th_struct *tsh with the u_char *t_header[4] values correctly as below?

0100 0111 .... .... .... .... .... .... = (0x00000047) tsh->s_byte .... .... 0... .... .... .... .... .... = 0 tsh->t_e_indicator .... .... .0.. .... .... .... .... .... = 0 tsh->p_u_s_indicator .... .... ..0. .... .... .... .... .... = 0 tsh->t_priority .... .... ...0 0100 1001 0011 .... .... = (0x00000493) tsh->id .... .... .... .... .... .... 00.. .... = (0x00000000) tsh->t_s_control .... .... .... .... .... .... ..01 .... = (0x00000001) tsh->a_f_control .... .... .... .... .... .... .... 0010 = 2 tsh->c_counter

Thank you!

c++
c
arrays
struct
binary
asked on Stack Overflow Dec 19, 2016 by swartkatt • edited Dec 19, 2016 by swartkatt

2 Answers

1

You can do something like this:

struct  th_struct t_header = {
    .s_byte = 0x47,
    .t_e_indicator = 0,
    .p_u_s_indicator = 0,
    .t_priority = 0,
    .id = 0x00000493,
    .t_s_control = 0,
    .a_f_control = 1,
    .c_counter = 2 };

and then: const struct th_struct* tsh = &t_header;

I think it's easier.

You must change the way you assing for sometinh like this:

u_char t_header[4];
t_header[0] = 0x47;     // s_byte
t_header[1] = (u_char)
        (0x00           // t_e_indicator
         | (0x00 << 1)  // p_u_s_indicator
         | (0x00 << 2)  // t_priority
         | (0x493 << 3)); // id[0..4]
t_header[2] = (u_char) ((0x493 << 3) >> 8); // id [5..12]
t_header[3] = (u_char)
        (0x00           // t_s_control
        | (0x01 << 2)   // a_f_control
        | (0x02 << 4)); // c_counter

const struct th_struct* tsh = (th_struct*)t_header;

Or change the struct order:

#pragma pack(push, 1)
           typedef struct th_struct2 {
               unsigned s_byte : 8;
               unsigned id1 : 5;
               unsigned t_e_indicator : 1;
               unsigned t_priority : 1;
               unsigned p_u_s_indicator : 1;
               unsigned id2 : 8;
               unsigned c_counter : 4;
               unsigned a_f_control : 2;
               unsigned t_s_control : 2;
           }th_struct2;
           #pragma pack(pop)

where id1 is the higher part od id, and id2 the lower part.

answered on Stack Overflow Dec 19, 2016 by JMA • edited Dec 19, 2016 by JMA
1

First of all you have a problem here:

u_char *t_header[4];

That is 4 pointers - not 4 u_char. You probably want:

u_char t_header[4];

Next problem is that the layout of bit fields is implementation-dependent.

Consequently, it is a bad idea (in general) to write code that assumes a specific layout. Such code will only be able to run on the specific system used when writing the code, i.e., the code is non-portable.

I recommend that you use the shift operator >> and bitwise and operator & to pick exactly the bits needed:

unsigned char t_header[4] = {0x47, 0x04, 0x93, 0x12};
th_struct tsh;

tsh.s_byte = t_header[0];
tsh.t_e_indicator = (t_header[1] >> 7) & 0x1;
tsh.p_u_s_indicator = (t_header[1] >> 6) & 0x1;
tsh.t_priority = (t_header[1] >> 5) & 0x1;
tsh.id = ((unsigned)(t_header[1] & 0x1f) << 8) + t_header[2];
tsh.t_s_control = (t_header[3] >> 6) & 0x3;
tsh.a_f_control = (t_header[3] >> 4) & 0x3;
tsh.c_counter = t_header[3] & 0xf;

printf("s_byte=%x\n", tsh.s_byte);
printf("t_e_indicator=%x\n", tsh.t_e_indicator);
printf("p_u_s_indicator=%x\n", tsh.p_u_s_indicator);
printf("t_priority=%x\n", tsh.t_priority);
printf("id=%x\n", tsh.id);
printf("t_s_control=%x\n", tsh.t_s_control);
printf("a_f_control=%x\n", tsh.a_f_control);
printf("c_counter=%x\n", tsh.c_counter);

Then you can also avoid having a packed struct.

answered on Stack Overflow Dec 19, 2016 by 4386427 • edited Dec 19, 2016 by TriskalJM

User contributions licensed under CC BY-SA 3.0