Russian Qt Forum
Ноябрь 22, 2024, 06:07 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4   Вниз
  Печать  
Автор Тема: чтение и запись битовых структур данных  (Прочитано 21078 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #15 : Апрель 27, 2021, 11:35 »

2) как сделать ширину поля частью структуры данных,
Не уверен что стоит ставить такую цель. Напр
Код
C++ (Qt)
struct A {
 int m_B;
 short m_C;
 ...
 char m_Z;
};
Если заменить int, short и.т.п. на нечто "содержащее битовый размер" (а это темплейт, другого не видно) это изрядно загадит текст, во всяком случае оперировать с членами будет трудно. Не применить ли KISS-прынцып (столь любимый некоторыми из нас  Улыбающийся). Простецкий вариант
Код
C++ (Qt)
void A::ReadWrite( CBitStream & stream, TMode mode )
{
 stream.ReadWriteInt(&m_B, 4, mode);    
 stream.ReadWriteShort(&m_C, 12, mode);
 ...
 stream.ReadWriteChar(&m_Z, 7, mode);
}
Он не так уж плох и работать будет.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #16 : Апрель 27, 2021, 11:50 »

kambala, поясните пожалуйста, как с таким требованием:

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

вы планировали задавать размеры полей здесь?

Код
C++ (Qt)
template<N, S>
struct Field {
 bool v // if N == 1
 int8_t v // if N <= 8 && S=signed
 uint8_t v // if N <= 8 && S=unsigned
 ...
};

Устанавливать максимальным? Тогда теряется смысл с наглядностью.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #17 : Апрель 27, 2021, 12:49 »

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

Нет, не законно=) Это опять возвращает нас к разговору о reinterpret_cast и type punning.
Единственный законный способ сделать type punning в современном с++ - это memcpy.
В с++20 добавят bit_cast который сейчас можно написать самому через memcpy

Код:
template <class To, class From>
typename std::enable_if_t<
    sizeof(To) == sizeof(From) &&
    std::is_trivially_copyable_v<From> &&
    std::is_trivially_copyable_v<To>,
    To>
// constexpr support needs compiler magic
bit_cast(const From& src) noexcept
{
    static_assert(std::is_trivially_constructible_v<To>,
        "This implementation additionally requires destination type to be trivially constructible");
 
    To dst;
    std::memcpy(&dst, &src, sizeof(To));
    return dst;
}

То есть можно скопировать буфер в структуру через memcpy а вот записать int64_t а потом прочитать из битфилда на него наложеннный - нет.
Но да, все известные мне компиляторы это позволяют делать. Но clang-tidy ругается AFAIK
Записан
juvf
Программист
*****
Offline Offline

Сообщений: 570


Просмотр профиля
« Ответ #18 : Апрель 27, 2021, 13:08 »

То есть можно скопировать буфер в структуру через memcpy а вот записать int64_t а потом прочитать из битфилда на него наложеннный - нет.
Но да, все известные мне компиляторы это позволяют делать. Но clang-tidy ругается AFAIK
А в чем косяк такого метода? Я понимаю когда объединили int и long. Но когда int и uint uint32_t и float - за каким углом, в какой архитектуре и с каким компилятором может быть подвох?

Это не то, чтобы "в с/с++ это предусмотрено и так нужно делать", это безопасный лайфхак. Если размер битовой структры 64 бита, и объединённого члена 64 бита, то компилятор не то что не позволит это сделать, или что-то испортит - а куда он денется с подводной лодки?
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #19 : Апрель 27, 2021, 13:15 »


Это не то, чтобы "в с/с++ это предусмотрено и так нужно делать", это безопасный лайфхак. Если размер битовой структры 64 бита, и объединённого члена 64 бита, то компилятор не то что не позволит это сделать, или что-то испортит - а куда он денется с подводной лодки?

все ненавистное UB нужно для оптимизаций.
Можно тот пример с reinterpret_cast переписать на union:

Код:
union U {
    int i{0};
    float f{0};
};

int foo()
{
        U u;
u.i = -1;
u.f = 0.0f;

return u.i; // 0 или -1?
}
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #20 : Апрель 27, 2021, 13:17 »

Не применить ли KISS-прынцып (столь любимый некоторыми из нас  Улыбающийся). Простецкий вариант
сейчас у меня примерно так и сделано, но не считаю, что это хорошее решение, надо попробовать поискать получше Улыбающийся
kambala, поясните пожалуйста, как с таким требованием:

вы планировали задавать размеры полей здесь?

Устанавливать максимальным? Тогда теряется смысл с наглядностью.
тот пример — для известных размеров. для неизвестных, думаю, надо немножко другой контейнер, который позволит задавать ширину поля в конструкторе. подлежащий тип будет максимальным, да. наглядности с неизвестными не достичь, конечно Улыбающийся
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
juvf
Программист
*****
Offline Offline

Сообщений: 570


Просмотр профиля
« Ответ #21 : Апрель 27, 2021, 13:24 »

Цитировать
0 или -1?
0

Цитировать
type punning
понятно... да это вариант с type punning
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Апрель 27, 2021, 15:24 »

тот пример — для известных размеров. для неизвестных, думаю, надо немножко другой контейнер, который позволит задавать ширину поля в конструкторе. подлежащий тип будет максимальным,
"Неизвестный" = содержит массив(ы) переменной длины, счетчик должен читаться/писаться в поток. Или есть др варианты?
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #23 : Апрель 27, 2021, 15:27 »

Цитировать
0 или -1?
ответом будет:
Код:
untitled 2:4:11: error: initializing multiple members of union
    float f{0};
          ^
untitled 2:3:9: note: previous initialization is here
    int i{0};
        ^
1 error generated.
Веселый

предлагаю вам ваше обсуждение об играх с юнионом перенести в другой тред Улыбающийся
"Неизвестный" = содержит массив(ы) переменной длины, счетчик должен читаться/писаться в поток. Или есть др варианты?
не понял, счетчик чего?

неизвестный на момент компиляции, в рантайме читается из конфигурационных файлов (они всегда доступны).
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #24 : Апрель 27, 2021, 15:28 »

P.S. вопрос знатокам Улыбающийся как задать массив (обычный или std::array) из std::byte по-человечески? у меня получается только с явным вызовом конструктора для каждого элемента как в коде выше. ([unsigned] char предлагать не надо Улыбающийся )
Код
C++ (Qt)
std::array c = {std::byte{0}, std::byte{0x78}, std::byte{0x2}};
нашел ответ: это так бай дизайн. лучше тогда брать uint8_t.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #25 : Апрель 27, 2021, 16:02 »

не понял, счетчик чего?
Счетчик эл-тов массива/контейнера - члена класса
неизвестный на момент компиляции, в рантайме читается из конфигурационных файлов (они всегда доступны).
А существующие файлы записанные с "конфигурацией X"? Выходит в поток все равно надо писать кол-во бит.
сейчас у меня примерно так и сделано, но не считаю, что это хорошее решение, надо попробовать поискать получше Улыбающийся
Может смущает просто отсутствие новомодных цацок? Улыбающийся Ну допустим даже удалось как-то объявить - от (полного) написания почленного I/O это все равно не избавит. И как битовые размеры (автоматом) сплавить для I/O - тоже хз.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #26 : Апрель 27, 2021, 16:20 »

Счетчик эл-тов массива/контейнера - члена класса
теперь понял. формат данных уже содержит такое поле.
А существующие файлы записанные с "конфигурацией X"? Выходит в поток все равно надо писать кол-во бит.
да, именно с такой конфигурацией. задачи конвертации между конфигурациями не стоит (но в принципе сделать можно).
Может смущает просто отсутствие новомодных цацок? Улыбающийся Ну допустим даже удалось как-то объявить - от (полного) написания почленного I/O это все равно не избавит. И как битовые размеры (автоматом) сплавить для I/O - тоже хз.
отсутствие не смущает, но не вижу ничего плохого в том, чтобы исследовать что в них есть и как ими можно воспользоваться для улучшения кода, уменьшения писанины и увеличения наглядности/читабельности Улыбающийся

надеюсь схитрить как-то через массив, задающий порядок полей, что-то типа:
Код:
for field in mystruct.orderedFields
  stream.write(field.size, field.value);
вроде бы на момент компиляции нельзя собрать массив полей структуры/класса? (без кодогенерации)
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #27 : Апрель 27, 2021, 16:39 »

отсутствие не смущает, но не вижу ничего плохого в том, чтобы исследовать что в них есть и как ими можно воспользоваться для улучшения кода, уменьшения писанины и увеличения наглядности/читабельности Улыбающийся
Да, я иногда тоже так рыпаюсь, пусть без особого успеха - но интересно
надеюсь схитрить как-то через массив, задающий порядок полей, что-то типа:
Код:
for field in mystruct.orderedFields
  stream.write(field.size, field.value);
вроде бы на момент компиляции нельзя собрать массив полей структуры/класса? (без кодогенерации)
Категорически утверждать "нельзя" не буду, но если и можно, то там такое мракобесие , что ну его нафиг, ото тупенько почленно расписать - сохранить и голову и время
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #28 : Апрель 27, 2021, 19:07 »

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

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #29 : Апрель 27, 2021, 20:40 »

А давайте попробуем придумать, как удобно можно описывать и использовать такие битовые структуры.
Вот один из возможных вариантов, так сказать для затравки (здесь пока все размеры полей задаются при компиляции):
Код
C++ (Qt)
 struct record
 {
   bit_field<1> flag;
   bit_field<4> mode;
   bit_field<9> address;
 
   bit_array pack() const
   {
     return ::pack( flag, mode, address );
   }
 
   static record  unpack( const bit_array &src )
   {
     record result;
     ::unpack( src, result.flag, result.mode, result.address );
     return result;
   }
 };
 
Записан
Страниц: 1 [2] 3 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.23 секунд. Запросов: 23.