Использование nibbles (4 битных переменных) в Windows C/С++
Я программирую заголовки сети, а много протоколов используют 4 битовых поля. Есть ли удобный тип, который я могу использовать для представления этой информации?
Самый маленький тип, который я нашел, - BYTE. Затем я должен использовать множество двоичных операций, чтобы ссылаться только на несколько бит внутри этой переменной.
Ответы
Ответ 1
Поскольку память адресована байтом, вы не можете адресовать какой-либо блок меньше, чем один байт. Однако вы можете создать struct
, который хотите отправить по сети, и использовать битовые поля следующим образом:
struct A {
unsigned int nibble1 : 4;
unsigned int nibble2 : 4;
};
Ответ 2
Развернувшись на Mehrdads, ответьте, также используйте объединение с байтом, чтобы избежать каких-то злобных бросков:
union Nibbler {
struct {
unsigned int first:4;
unsigned int second:4;
} nibbles;
unsigned char byte_value;
}
Ответ 3
Кажется, что все любят использовать бит-поля в struct
для этого. Лично я переношу весь свой код пакета в объекты, чтобы вы не видели кишок. Проблема, которую я нашел с использованием битовых полей для кода протокола, заключается в том, что она поощряет использование структур в качестве наложений в памяти. Вы можете сделать это безопасно, но вы должны быть мучительно осторожны, чтобы убедиться, что вы правильно разбираетесь в проблемах с энзином и упаковкой. Если у вас действительно нет веской причины (например, вы пишете код, который получает пакет Ethernet из области ввода-вывода с отображением памяти), тогда использование бит-полей, наложенных на память, создает чрезвычайно хрупкий код IMHO.
Мне намного легче написать класс Packet
, который реализует процедуры извлечения, вставки и перезаписывания в различные битовые ширины. Затем вы реализуете свой код обработки пакетов с точки зрения извлечения значений определенной ширины из смещений в собственные целые числа, а какие нет. Скрыть все проблемы с энтерианностью и упаковкой за абстракцией до тех пор, пока профилирование не докажет, что накладные расходы слишком велики.
Это один из тех уроков, которые я хотел бы узнать много лет назад... вы можете подумать, что переносимость кода не проблема, и не является энтузиазмом. Поверьте мне, количество головных болей, которые вас приводят, когда ваш компилятор меняет свой алгоритм заполнения или переключается на другой компилятор, убедит вас в том, что наложения - очень плохая идея для кода сетевой обработки пакетов.
Ответ 4
Использовать поля в структуре:
struct Header
{
unsigned int lowestNibble : 4;
unsigned int anotherNibble : 4;
unsigned int : 18; # Unnamed padding.
bool aBool : 1;
bool anotherBool : 1;
unsigned int highestNibble : 4;
};
: 4
указывает, что запись должна занимать 4 бита. Вы можете использовать любое количество бит, которое вам нравится. Вы можете использовать любой встроенный тип, который вам нравится.
Обычно вы вставляете указатель на свои данные в Header *
, а затем делаете что-то вроде:
pHeader->lowestNibble = 5;
Ответ 5
Нет, нет удобных типов для кусков. Но его легко сделать с помощью макросов или с помощью шаблонов. Это хорошо работает, если/когда вам нужно иметь дело с endian-ness.
Foredecker