Как изменить 4 бита в неподписанном символе? - PullRequest
4 голосов
/ 21 января 2011
unsigned char *adata = (unsigned char*)malloc(500*sizeof(unsigned char));
unsigned char *single_char = adata+100;

Как изменить первые четыре бита в single_char для представления значений между 1..10 (int)?

Вопрос возник из структуры заголовка TCP:

Data Offset: 4 bits 

The number of 32 bit words in the TCP Header.  This indicates where
the data begins.  The TCP header (even one including options) is an
integral number of 32 bits long.

Обычно он имеет значение 4..5, значение char равно 0xA0.

Ответы [ 4 ]

6 голосов
/ 21 января 2011

Предполагается, что вы инициализировали * single_char некоторым значением.В противном случае опубликованное решение caf делает то, что вам нужно.

(*single_char) = ((*single_char) & 0xF0) | val;

  1. (*single_char) & 11110000 - Сбрасывает младшие 4 бита в 0
  2. | val -- Устанавливает последние 4 бита в значение (при условии, что val <16) </li>

Если вы хотите получить доступ к последним 4 битам, вы можете использовать unsigned char v = (*single_char) & 0x0F;

Если вы хотите получить доступстаршие 4 бита вы можете просто сдвинуть маску на 4, т.е.

unsigned char v = (*single_char) & 0xF0;

и установить их:

(*single_char) = ((*single_char) & 0x0F) | (val << 4);

5 голосов
/ 21 января 2011

Это установит старшие 4 бита *single_char в смещение данных и очистит младшие 4 бита:

unsigned data_offset = 5; /* Or whatever */

if (data_offset < 0x10)
    *single_char = data_offset << 4;
else
    /* ERROR! */
2 голосов
/ 21 января 2011

Вы можете использовать битовые операторы для доступа к отдельным битам и изменения в соответствии с вашими требованиями.

1 голос
/ 08 октября 2017

Я знаю, что это старый пост, но я не хочу, чтобы другие читали длинные статьи о побитовых операторах, чтобы получить функцию, подобную этой -

//sets b as the first 4 bits of a(this is the one you asked for
void set_h_c(unsigned char *a, unsigned char b)
{
    (*a) = ((*a)&15) | (b<<4);
}

//sets b as the last 4 bits of a(extra)
void set_l_c(unsigned char *a, unsigned char b)
{
    (*a) = ((*a)&240) | b;
}

Надеюсь, это поможет кому-то в будущем

...