- Muchas notas - Fran Acién

20230515 - C bit fields packing and hexdump

I am running with a common problem that I find over the years in C, the C bit fields poacking.

The conclusion of making some tests are:

  1. Bit fields structures are for creating structures with the least memory possible
  2. Little endian and big endian is how the variables are saved into memory. In systems with different architecture this part will be sensitive.
  3. Fromt hese example we can see that is MSB firsts but the structures are sorted from the lower bit to higher. That is that version field in example 1 is at bits 0:2 in MSB, however from the CCSDS specification it is defined as bit 0 the first to be sent, however in this frame the first bit to be sent will be the bit 7, then 6 then 5 and so on. So the buffer represented is different in the example than with the CCSDS specification.

Be careful with HEX dump

0df64172c7eaf823584d85cf82688115.png

Be careful with hexdump. The first 4 digits is the first 2 bytes, where “01” is the second byte of the transmission and “20” is the first byte of the transmission.

Use the command xxd instead.

example 0

I am going to write about how data are packed on C.

struct t1 // 6 bytes
{
    int a:12; // 0:11
    int b:32; // 12:43
    int c:4;  // 44:47
}__attribute__((packed));

Example 1

  • Version: 0b001
  • type: 0b0
  • sec_header_flag: 0b0
  • proc_id: 0b00000000011
  • seq_flags: 0b11
  • seq_cnt: 0b0
  • length: 0b110
typedef struct {
    unsigned short version : 3;
    unsigned short type : 1;
    unsigned short sec_header_flag : 1;
    unsigned short proc_id : 11;
    unsigned short seq_flags : 2;
    unsigned short seq_cnt : 14;    //Seq count or packet name
    unsigned short length;
} CCSDS_primary_header;

When printing is like:

76543210 and so on. The first bit represented is the bit 7, and the last of the octet is the 0.

01100001 00000000 00000011 00000000 00000110 00000000

Printing like:

void print_binary(unsigned char byte){
    for (int i = 7; i >= 0; i--) {
        printf("%d", (byte & (1 << i)) ? 1 : 0);
    }
}

...

for (int i = 0; i < 6; i++) {
    print_binary(ott[i]);
    printf(" ");
}

How to extract the info

unsigned char buffer = 0b10111010; // assume buffer contains the byte you want to extract the parameters from
    unsigned char version = (buffer >> 5) & 0b111; // extract the first 3 bits (bits 7-5) and mask the rest using bitwise AND operation
    unsigned char type = (buffer >> 4) & 0b1; // extract the next 1 bit (bit 4) and mask the rest using bitwise AND operation
    unsigned char flag = (buffer >> 3) & 0b1; // extract the next 1 bit (bit 3) and mask the rest using bitwise AND operation
    unsigned char id = buffer & 0b111; // extract the last 3 bits (bits 2-0) and mask the rest using bitwise AND operation