简体   繁体   中英

Printing a 2 bytes packet

There is a 2 byte packet. The first 5 bits represent the version, the next 5 bits represent the type, and the last 6 bits represent the value. I am passing the packet as a char* to a function ( print_pak ). In that function, I want to print the version, type, and packet value. How can I do that?

void print_pak(char* pak)
{
}

You need to use bit masking and shifting for this. Also, when doing bit manipulation, I believe it's preferred to work with unsigned integer types since the binary representation of negative integers is not defined by the C standard.

void
print_pak(const unsigned char *pak)
{
    unsigned char version, type, value;

    version = (pak[0] >> 3);
    type = ((pak[0]&0x07) << 2) + (pak[1] >> 6);
    value = pak[1]&0x3f;

    printf("Version = %u, Type = %u, Value = %u\n", version, type, value);
}

Here's how this works. The << and >> operators are for bit shifting. Suppose you have an unsigned char , x , which holds the bits 10111010. Shifting it right by 3 bits is done by (x >> 3) (operator precedence always trips me up when doing bit manipulation so I throw in parentheses to be safe). The right three bits can't go anywhere and so they fall off. The result is 00010111. Shifting to the left works the same (sort of).

Bit masking, & , implements binary "and". That is, if x is 10101011 and y is 00011111, then x&y only has 1's where x and y share them. So, it would be 00001011.

Let's take all of this and tackle your problem. The version is the first five bits of the first byte. Therefore, we want to right shift the low three bits off.

The type is the last three bits of the first byte followed by the first two bits of the second byte. That first group can be acquired by masking off the high five bits of the first byte ( 0x07 is 00000111 in binary). The second group can be acquired by right shifting the second byte by six bits. Then, to put them together, you need to left shift the first group by two bits to make room for the second group.

Finally, the value is the low six bits of the second byte which can be acquired by a simple masking of those bits ( 0x3f is 00111111 in binary).

You can do something like the following inside your print function:

uint16_t *data = (uint16_t*)pak;
unsigned char version = *data & 0b0000000000011111; //only read the 5 least significant bits
unsigned char type = (*data & 0b0000001111100000) >> 5; //only read bit 6 to 10, then shift the result to the right by 5 bits
unsigned char value = (*data & 0b1111110000000000) >> 10; //only read the 6 most significant bits, then shift the result to the right by 10 bits

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM