| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Размещение в памяти полей структур |
| Автор: Курсант 24.10.2014, 08:21 | ||||||||
| Всем доброго времени суток! У меня есть указатель void*, когда я пытаюсь читать из памяти структуру, расположенную по этому адресу, то первое поле читается нормально, второе - сдвинуто на 2 байта, третье - на 4 байта, то есть структура из памяти читается в искажённом виде. Конкретно: занимаюсь разбором Ethernet-пакета, пакет считан из буфера приёмника в область памяти, есть указатель на область памяти void* Pointer. Сам пакет содержит в себе запрос от протокола ARP при подключении моего устройства в локальную сеть, хотя это не принципиально.
Для удобства работы у меня есть структуры Ethernet_Header, MAC_Address, Protocol_ID_in_Ethernet
Работая с указателем на пакет как с указателем на структуру Ethernet_Header, я пытаюсь выяснить, пакет какого протокола содержится в данных пакета Ethernet. Для этого я считываю из области памяти, на которую указывает Pointer, структуры типа MAC_Address и Protocol_ID_in_Ethernet:
После этого в переменных я получаю следующие значения
Я исходил из того, что в структуре не предусмотрены пропуски в два байта между полями. Компилятор почему-то посчитал по другому. Я наверное попробую объявить переменную типа Ethernet_Header и считать туда весь заголовок, но вообще изначально я не хотел ничего считывать ни в какие переменные, а использовать в качестве переменной саму область памяти, используя Pointer в качестве указателя. Т.е. мне не хотелось бы заниматься копированием области памяти, скопированной из буфера приёмника - это уже явно избыточные операции. Собственно вопрос: кто виноват и что делать? З.Ы. Компилятор CMC-ARM (для контроллеров с ARM-архитектурой). |
| Автор: xvr 24.10.2014, 09:55 | ||||
Стандарт С99, параграф 6.7.2.1 (Structure and union specifiers)
так что имеет право В С++ есть аналогичное замечание в п 9.2 абзац 21 -
Попробуйте аттрибут (или прагму) packed (не знаю, как она называется у CMC-ARM) |
| Автор: Dem_max 24.10.2014, 10:49 | ||
используй
|
| Автор: tzirechnoy 24.10.2014, 19:23 |
| Я посоветую не использовать прагмапаков, а работать с char *. Поначалу -- избавит от кучи проблем с пакингом, размером полей, byte order и прочей гадостью. При этом выигрыш от описания структур как структур -- в общем невелик, намакросах можно написать почти такжэ понятно, при этом скорость редко где уменьшытся, поскольку компиляторы обычно могут сокращать константные вычисления. |
| Автор: Курсант 24.10.2014, 21:02 | ||||||
| Спасибо всем за ответы! Прагма пак на CMC, похоже, не работает, а для отключения выравнивания полей структур есть директива __packed. У меня всё заработало, точнее, заголовок Ethernet-пакета удалось разобрать именно на те составляющие, из которых он состоит. Но дальше возникли трудности с разбором заголовка ARP-пакета, вложенного в Ethernet-пакет. А именно, структура заголовка Ethernet-пакета описывается так: EthernetProtocol.h
До этого места всё работает нормально. Но как только я поправляю аналогичным образом описание заголовков ARP-пакетов: ARPProtocol.h
Начинаются проблемы. При компиляции появляется ругань на вот этот участок кода: EthernetProtocol.h
при этом даже если из EthernetProtocol.h убрать директивы packed, сообщения об ошибках всё равно остаются. То есть возникают проблемы, если в packed-структуре есть другие вложенные структуры. И я опять завис. |
| Автор: tzirechnoy 24.10.2014, 22:44 |
| Это у Вас не вложэнные структуры, а дважды включённые файлы заголовков. |
| Автор: Курсант 24.10.2014, 22:54 | ||||
Ну, в файлах заголовков у меня стоит
Поэтому дважды включение вроде бы исключено. А во-вторых как-то странно получается - добавляю __packed в описание структур ARP-заголовка, и сразу появляется два включения файла заголовка. Убираю __packed из описания структур ARP-заголовка - и всё компилируется (но на уровне ARP, судя по всему, работает неправильно). |
| Автор: tzirechnoy 25.10.2014, 11:22 | ||
То есть то, что у вас написано там вверху после слова "код" -- это фигня и не соответствует действительности. В общем, я мог бы догадаться и сам, да. Печально, но вряд ли здесь найдётся много жэлающих пытаться разбираться в секретном коде. |
| Автор: Курсант 25.10.2014, 13:13 | ||||
Мда, Вы правы, извините, но дело в том, что заголовочные файлы и си-файлы у меня достаточно объёмные, и приводить их полностью я посчитал излишним... Думаю, копаться в них нашлось бы ещё меньше желающих. Как ни странно, с ARP-заголовками работа идёт нормально даже без директив __packed. То ли компилятору одной директивы оказалось достаточно. Ну, я достаточно начинающий программист, поэтому пока займусь протоколами, а с директивами компилятора разберусь как-нибудь потом. Это работает, значит не будем ничего трогать. Спасибо большое за ответы. |