C хранит 2 числа в одном байте - PullRequest
1 голос
/ 27 октября 2011
u_char  ip_vhl;     /* version << 4 | header length >> 2 */

Я не могу понять это правильно, как это сделать? Можете ли вы привести примеры использования этого байта для хранения этих двух чисел? зная, что каждый из них 4 бит

Ответы [ 5 ]

5 голосов
/ 27 октября 2011

Если каждое число составляет 4 бита, вы собираетесь использовать 8 самых младших битов символа.Во многих случаях это будут все имеющиеся биты.

Сделайте это так:

ip_vhl = ((version & 15) << 4) | (length & 15);

Предполагая, что version - это то, что вам нужно в старших битах, и length это то, что вы хотите в самых младших битах.& 15 гарантирует, что каждое значение имеет только 4 бита.Это в основном необходимо для значения length, чтобы избежать перезаписи битов, выделенных для version, если длина больше 15. Десятичная константа 15 будет записана в шестнадцатеричном виде (как 0xf или 0x0f) какдля многих это вопрос стиля и вкуса, который вы находите чище.

Другой способ записать «целое число, для которого n крайних правых битов установлено в 1, а все остальные в 0» - ((1 << n) - 1)и, поскольку здесь n = 4 мы можем использовать ((1 << 4) - 1), что, конечно, оценивается как 15.

Ваш код, кажется, сначала делится на length и сохраняет его, если это то, что вы хотите сделатьВы должны сделать это перед упаковкой в ​​сингл char, для ясности:

length >>= 2;  /* Convert from bytes to 32-bit words (or whatever). */
ip_vhl = ((version & 15) << 4) | (length & 15);
2 голосов
/ 27 октября 2011

Версия (а) с использованием битовых полей

struct entry {
  unsigned char version : 4;
  unsigned char length  : 4;
} ip_vhl;

ip_vhl.version = version;
ip_vhl.length = length;

Версия (б) арифметики

ip_vhl = (version << 4) | (length & 0xF)
version = ip_vhl >> 4;
length  = ip_vhl & 0xf;
1 голос
/ 27 октября 2011

Кроме того, вы можете прибегнуть к структуре с битовыми полями:

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));

Или вы можете упаковать структуру с объединением без знака без знака, чтобы получить весь байт за один раз:

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;
1 голос
/ 27 октября 2011
ip_vhl = (version << 4) | (headerlen & 0xf);

Тогда байт будет выглядеть так:

VVVVHHHH

Чтобы вернуть исходные значения:

version = ip_vhl >> 4;
headerlen = ip_vhl & 0xf;
1 голос
/ 27 октября 2011
// 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...