LINUX.ORG.RU

Битовые поля

 


0

1
struct Date {
   unsigned short nWeekDay  : 3;    // 0..7   (3 bits)
   unsigned short nMonthDay : 6;    // 0..31  (6 bits)
   unsigned short nMonth    : 5;    // 0..12  (5 bits)
   unsigned short nYear     : 8;    // 0..100 (8 bits)
};

А почему за использование таких вещей нужно убивать?


Оно платформоспецифично и тормозит. Такая штука может понадобится только для того, чтобы разбирать какой-то бинарный формат где-нибудь на кофеварке embeded.

Ну т.е. делать так Date просто «шоб було» точно не надо.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)

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

Вот посмотри:

https://gcc.godbolt.org/z/YBjaGh

в битовых полях используются битовые операции, ваш кэп.

fsb4000 ★★★★★
()
Ответ на: комментарий от SZT

Мне один мальчик сказал что использование приведет к плаформ-зависимому коду, а это ошибки и непредсказуемое поведение и программисты их использующие непрофессионалы и их нужно убивать. Он типа царя короче возил мордой по столу.

Liz812
() автор топика

0..7 (3 bits)

Ну… окей.

0..31 (6 bits)

Пяти бит хватит.

0..12 (5 bits)

Четырёх бит хватит.

0..100 (8 bits)

Семи бит хватит.

i-rinat ★★★★★
()
Ответ на: комментарий от Liz812

что использование приведет к плаформ-зависимому коду

Если структуры из памяти писать в файл как есть, то да, будет зависеть от платформы. Но проблемы с выравниванием будут и без битовых полей. Если структуры только в памяти, то проблем от использования не будет. Разве что специально себе в ноги стрелять.

i-rinat ★★★★★
()
Ответ на: комментарий от Liz812

Мне один мальчик сказал что использование приведет к плаформ-зависимому коду, а это ошибки и непредсказуемое поведение

Порядок следования этих битовых полей действительно строго не определен. В общем да, есть ньюансы, если ты делаешь структуру с битовыми полями и записываешь ее в файл, а потом такой файл читаешь прогой с той же структурой с битовыми полями, может получаться что-то не то. См. например http://mjfrazer.org/mjfrazer/bitfields/

Впрочем, даже если просто какие-то инты записывать, на одной платформе они могут быть little, на другой big endian и это надо учитывать.

Он типа царя короче возил мордой по столу.

Царя уже забанили, можешь удаленные почитать в В чем отличие процедурного программирования от функционального?

SZT ★★★★★
()
Ответ на: комментарий от SZT

little, на другой big endian и это надо учитывать.

А почему компилятор не учитывает? Он знает на какой платформе запущен.

Liz812
() автор топика
Ответ на: комментарий от Liz812

Ну вообще он знает под какую платформу он компилирует. Если у тебя на одной платформе little endian, на другой big endian, и если у тебя код который тупо записывает 16-битный unsigned тип, ну например число 123 в файл через fwrite, то одна программа тебе запишет {0, 123} другая {123, 0}

SZT ★★★★★
()
Последнее исправление: SZT (всего исправлений: 1)
Ответ на: комментарий от Liz812

плаформ-зависимому коду

Это не всегда плохо.

и непредсказуемое поведение

На мультиплатформе мб. А на одной платформе и одном компиляторе все ок.

Dudraug ★★★★★
()
Ответ на: комментарий от Liz812

Да пофиг на опенсорс, речь о плохом стиле программирования.

Данный код таким не является, если написан осознано и по необходимости. Некоторые и goto и break из цикла плохим стилем считаются.

Dudraug ★★★★★
()
Ответ на: комментарий от SZT

Речь идет о структуре в памяти. Почему компилятор не делает так, чтобы автоматически рассовывать байты в нужном порядке? Я ведь на С++ пишу а не ассемблере чтобы еще думать про порядок байт.

Liz812
() автор топика

Убивать надо за любое необычное решение не вызванное конкретной необходимостью. При прочих равных выбирать надо всегда самый простой и общеупотребимый вариант.

morse ★★★★★
()
Ответ на: комментарий от Liz812

Почему компилятор не делает так, чтобы автоматически рассовывать байты в нужном порядке?

А какой порядок нужный? Если тебе известно какой нужный, бери и конвертируй в нужный.

SZT ★★★★★
()
Ответ на: комментарий от Liz812

Я ведь на С++ пишу а не ассемблере чтобы еще думать про порядок байт.

С++ это всего лишь C с приделанными костылями. Бери более высокоуровневые языки, которые спасут тебя от думанья над всякими там порядками байт

SZT ★★★★★
()
Ответ на: комментарий от Liz812
struct {
  unsigned a : 3;
  unsigned b : 3;
  unsigned c : 3;
} a;

a.a = 1;
a.b = 2;
a.c = 3;

printf("%d %d %d\n", a.a, a.b, a.c);

Код выше будет печатать одно и то же и на little-endian, и на big-endian. Пока структуры исключительно в памяти и ты не получаешь доступ к ним через псевдонимы, а обращаешься исключительно по именам полей с их типами, порядок байт процессора значения не имеет.

i-rinat ★★★★★
()
Ответ на: комментарий от morse

Битовые поля для удобсва и уменьшения ошибок придумали специально придумали. Гораздо проще присвоить значение в поле чем корячиться с битами, масками и сдвигами.

Liz812
() автор топика
Ответ на: комментарий от anonymous

Там не «год», там 0..100. Если хочешь там года хранить, нужно формулировку задачи фиксить, а не пытаться костыли подставлять.

i-rinat ★★★★★
()

С битовыми полями нет никаких проблем, пока ты не пытаешься сериализовывать их на архитектуре с другим порядком байт. Ну и скорость, хотя, IMHO, там, где они используются (ввод-вывод), это не столь критично

XMs ★★★★★
()
Ответ на: комментарий от i-rinat

Пока структуры исключительно в памяти и ты не получаешь доступ к ним через псевдонимы, а обращаешься исключительно по именам полей с их типами, порядок байт процессора значения не имеет.

Имеет иначе я бы не начала этот топик.

Liz812
() автор топика
Ответ на: комментарий от morse

Убивать надо за любое необычное решение не вызванное конкретной необходимостью. При прочих равных выбирать надо всегда самый простой и общеупотребимый вариант.

This. Но обычно битовые полня без необходимости никто не использует.

Dudraug ★★★★★
()
Ответ на: комментарий от Liz812

Имеет иначе я бы не начала этот топик.

В какой ситуации?

Dudraug ★★★★★
()
Ответ на: комментарий от Liz812

А какой порядок нужный? он знает под какую платформу он компилирует

Сам написал.

Не понимаю смысла твоего сообщения.

SZT ★★★★★
()
Ответ на: комментарий от Liz812

Ну вот и отлично. На одной платформе у него нужный порядок один, на другой - другой. Если тебе нужно привести все к общему знаменателю - делай это в явном виде

SZT ★★★★★
()
Последнее исправление: SZT (всего исправлений: 1)
Ответ на: комментарий от Dudraug

Ты тоже считаешь, что битовые операции с ручным подсчетом битов более простой и надежный способ? Зачем мне подменять компилятор когда он сам умеет работать с битовыми полями?

Liz812
() автор топика
Ответ на: комментарий от XMs

С битовыми полями нет никаких проблем, пока ты не пытаешься сериализовывать их на архитектуре с другим порядком байт.

Можно проверять порядок байт и преобразовывать в нужный в процессе сериализации.

Meyer ★★★★★
()
Ответ на: комментарий от SZT

Почему я а не компилятор? Выражение 1+2+3 работает везде одинаково, поскольку компилятор об этом заботится. Почему он не може такого сделать с битовыми полями и закрыть вопрос о платформозависимости.

Liz812
() автор топика
Ответ на: комментарий от Liz812

Объясни мне какая связь между днем недели и ручным подсчетом битов?

Структура приведенная тобой в примере однозначно плохая. Битовые поля для даты не нужны. Необходимость их использования в каждом случае должна рассматриваться отдельно. Естественно бывают случаи когда они нужны, иначе бы их не было. Этот – не один из таких случаев.

morse ★★★★★
()
Ответ на: комментарий от Liz812

Почему он не може такого сделать с битовыми полями и закрыть вопрос о платформозависимости.

Обратись в комитет по стандартизации C++ с таким предложением.

SZT ★★★★★
()
Ответ на: комментарий от Meyer

Это если ты знаешь о том, что такая вещь, как порядок байт, вообще существует. А если абстрактный быдлокодер тупо возьмёт считанный массив байтов и пройдётся по нему указателем на битовое поле, его могут ждать сюрпризы. Я вот о чём

XMs ★★★★★
()
Ответ на: комментарий от Liz812

Ты тоже считаешь, что битовые операции с ручным подсчетом битов более простой и надежный способ? Зачем мне подменять компилятор когда он сам умеет работать с битовыми полями?

А теперь можно перефразировать? Я, лично, мысли не понял.

Dudraug ★★★★★
()
Ответ на: комментарий от Meyer

Вот и проблема и решение сразу. Это работает везде.

struct iphdr
  {
#if __BYTE_ORDER == __LITTLE_ENDIAN
    unsigned int ihl:4;
    unsigned int version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
    unsigned int version:4;
    unsigned int ihl:4;
Liz812
() автор топика
Ответ на: комментарий от Liz812

То есть тебя ругали не за использование битового поля, а за использование битового поля вместо коряченья с битами, масками и сдвигами? Где-то нужна была битовая маска, скажем, из 16 бит и ты вместо нее зафигачила структуру с битовыми полями? Ну, это и правда требует знания о порядке байт и прочем паддинге. Правильно ругали.

roof ★★
()
Ответ на: комментарий от roof

А теперь прикинь что мне нужно несколько раз упаковать данные ручками в 128 бит? Сколько раз я ошибуся с битами, масками и сдвигами? Вместо обычных операций присваивания?

Liz812
() автор топика
Ответ на: комментарий от Liz812

Тесты спасут тебя, пиши тесты, не только код

fsb4000 ★★★★★
()
Ответ на: комментарий от Liz812

Это работает везде.

Это работает в ядре, потому что ядро собирается с -fno-strict-aliasing. Принято там так кодить. Обычно с такими флагами софт не собирают, потому что он немного вредит оптимизациям.

i-rinat ★★★★★
()
Ответ на: комментарий от Liz812

Хм, можешь конкретнее? Если что-то делается несколько раз, оно выносится в метод или функцию, и тогда уже не важно, сколько раз ее надо вызвать. Если получаются какие-то сложные комбинации масок и сдвигов их можно оформить как макросы (или методы, или функции) и не париться. А у тебя в примере структуры даже pragma pack нету, откуда ты знаешь ее размер? Может, там и не 128 бит, а, скажем, 132?

roof ★★
()
Ответ на: комментарий от roof

какие-то сложные комбинации масок и сдвигов их можно оформить как макросы

Да ну нафиг это еще один источник очень трудных ошибок. Куда проще нарисовать в 128 клеточках на бумажке границы разным цветом и заполнить длину полей в стуктуру.

Liz812
() автор топика
Ответ на: комментарий от Liz812

Куда проще нарисовать в клеточках крестики разными цветами а потом вышить получившуюся картинку ниточками. Но ты ведь программировать хочешь? Битовые поля нужны для уменьшения размера структруры ценой снижения производительности при доступе к этим полям. Чтобы ее использовать для упаковки данных в какой-то предсказуемый формат, надо вокруг нагородить кучу кода, который как раз легко написать неправильно, но когда он сломается, тебя уже уволят и придется разбираться какому-то невиновному человеку.

roof ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.