Reputation: 617
u_char ip_vhl; /* version << 4 | header length >> 2 */
I can't get it right , how is this done ? can you give me examples on how to use this byte to store these 2 numbers knowing that each one is 4 bit
Upvotes: 1
Views: 1823
Reputation: 400159
If each number is 4 bits, you're going to use the 8-most lower bits of the character. In many cases, this will be all the bits there are.
Do it like so:
ip_vhl = ((version & 15) << 4) | (length & 15);
Assuming version
is the one you want in the upper bits, and length
is what you want in the lower-most bits. The & 15
makes sure each value only is 4 bits. This is mostly needed for the length
value, to avoid overwriting bits dedicated to the version
if length is larger than 15. The decimal constant 15
would be written in hex (as 0xf
or 0x0f
) by many people, it's a matter of style and taste which you find cleaner.
Another way of writing "an integer with the n right-most bits set to 1, and all other set to 0" is ((1 << n) - 1)
, and since here n = 4
we could use ((1 << 4) - 1)
, which of course evaluates to 15
.
Your code seems to divide length
down first and store that, if that's what you want to do you should do it before packing it into the single char
, for clarity:
length >>= 2; /* Convert from bytes to 32-bit words (or whatever). */
ip_vhl = ((version & 15) << 4) | (length & 15);
Upvotes: 5
Reputation: 2834
Also, you can resort to a structure with bit fields:
typedef struct s_ip_vhl
{
int version : 4;
int header_length : 4;
} ip_vhl_type;
ip_vhl_type my_ip_vhl;
my_ip_vhl.version = 4;
my_ip_vhl.header_length = 5;
unsigned char byte = *((byte*)(&my_ip_vhl));
Or you can pack the struct with a union with unsigned char to get the entire byte in one go:
typedef union u_ip_vhl
{
typedef struct s_ip_vhl
{
int version : 4;
int header_length : 4;
} ip_vhl_type;
unsigned char byte;
} ip_vhl_union;
Upvotes: 1
Reputation: 31281
Version (a) using bit fields
struct entry {
unsigned char version : 4;
unsigned char length : 4;
} ip_vhl;
ip_vhl.version = version;
ip_vhl.length = length;
Version (b) arithmetics
ip_vhl = (version << 4) | (length & 0xF)
version = ip_vhl >> 4;
length = ip_vhl & 0xf;
Upvotes: 2
Reputation: 318808
ip_vhl = (version << 4) | (headerlen & 0xf);
Then the byte will look like this:
VVVVHHHH
To get back the original values:
version = ip_vhl >> 4;
headerlen = ip_vhl & 0xf;
Upvotes: 1
Reputation: 111950
// Here we are trusting that version and length are both < 0xF
unsigned char ip_vhl = (unsigned char)version << 4 | (unsigned char)length;
unsigned char version = ip_vhl >> 4;
unsigned char length = ip_vhl & 0xF;
Upvotes: 1