Перейти к содержанию
    

Доступ к полям структуры.

Просто хочу, как бывший советский гражданин, дать несколько советов.

Когда имеете дело со структурами, особенно отображающими пакеты данных, не забывайте endianness(простите не знаю как по-русски). Кроме того, советую включать файл stdint.h и использовать типы int8_t, uint16_t и тому подобное- это существенно облегчает как понимание, так и переносимость кода.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Просто хочу, как бывший советский гражданин, дать несколько советов.

Когда имеете дело со структурами, особенно отображающими пакеты данных, не забывайте endianness(простите не знаю как по-русски). Кроме того, советую включать файл stdint.h и использовать типы int8_t, uint16_t и тому подобное- это существенно облегчает как понимание, так и переносимость кода.

Спасибо, учёл.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Просто хочу, как бывший советский гражданин, дать несколько советов.

Когда имеете дело со структурами, особенно отображающими пакеты данных, не забывайте endianness(простите не знаю как по-русски). Кроме того, советую включать файл stdint.h и использовать типы int8_t, uint16_t и тому подобное- это существенно облегчает как понимание, так и переносимость кода.

По-русски это будет эндианность :)

А я вообще не рекомендую мапить протоколы на структуры, потому как нарвался однажды на грабельное поле, и связано это было с выравниванием.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И какой в этом вообще смысл?

 

чем это бы отличалось если не использовать вложенную анонимную структуру вообще.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А я вообще не рекомендую мапить протоколы на структуры, потому как нарвался однажды на грабельное поле, и связано это было с выравниванием.

А вот это напрасно. Если кто-то упаковывается данные, то, скорее всего, кто-то будет распаковывать. Такие вещи хорошо включать в заголовочный файл, который используется с обеих сторон.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вот это напрасно. Если кто-то упаковывается данные, то, скорее всего, кто-то будет распаковывать.

Смотрим C99 Annex J - Portability issues:

— The order of allocation of bit-fields within a unit (6.7.2.1).

— The alignment of non-bit-field members of structures (6.7.2.1). This should present

no problem unless binary data written by one implementation is read by another.

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

 

Ну, добавим пару исключений:

- можно в рамках одной архитектуры и компилятора (что очевидно)

- можно в случае проверки корректности упаковки на этапе сборки

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вот это напрасно. Если кто-то упаковывается данные, то, скорее всего, кто-то будет распаковывать. Такие вещи хорошо включать в заголовочный файл, который используется с обеих сторон.

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

Можно и методы сделать одинаковыми для C++. Я делаю так:

struct u16p8 {
 u8 bytes[2];
 operator u16() const { return u16load(&bytes); }
 u16p8 & operator =(u32 val) { u16save(&bytes, val); return *this; }
};
struct u32p8 {
 u8 bytes[4];
 operator u32() const { return u32load(&bytes); }
 u32p8 & operator =(u32 val) { u32save(&bytes, val); return *this; }
};

где: u16load(), u16save(), u32load(), u32save() - макросы, определённые по-разному в соответствии с платформой.

Если для Cortex-M3 и x86 к примеру u16load() будет:

#define u16load(p) (*(u16 *)p)

то для ARM7/9:

#define u16load(p) (*(u8 *)(p) | (u16)((u8 *)(p))[1] << 8)

Таким образом я совершенно свободно перетаскиваю структуры, описывающие пакованные структуры, между разными платформами.

Это очень полезно когда пишешь firmware и тут же пишешь клиентское ПО на PC (для этого устройства) и надо описать протокол взаимодействия - это можно делать в одном файле просто копируя его между двумя проектами.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По-русски это будет эндианность :)

А я вообще не рекомендую мапить протоколы на структуры, потому как нарвался однажды на грабельное поле, и связано это было с выравниванием.

Я эту "проблему" решаю так

#pragma push
#pragma pack(1)
……………………
#pragma pop

Предпочитаю структуры, нагляднее. Встречал код, где данные в выходной массив просто по смещениям вписываются. Мне не нравится. Вообще - на вкус и цвет, главное что бы работало и правильно:).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я эту "проблему" решаю так

...

Лучше:

#pragma pack(push, 1)

#pragma pack(pop)

Но только это к сожалению не во всех компиляторах работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Практически каждый компилятор/процессор имеет своё решение. Мои советы не имеют конкретной привязки, это более вопрос стиля, подхода, школы, если хотите. А не хотите - не надо. Для меня это АБСОЛЮТНАЯ необходимость и, по-этому, я ищу и пока всегда находил способы, как её добиться для всех комбинаций, которые мне пришлось встречать. Если есть конкретный вопрос для конкретной архитектуры и компилятора буду рад попробовать помочь.

Изменено пользователем pitt

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...