-
- А структуры объявлены через typedef или непосредственно? - IBAH(07.04.2020 21:03)
- typedef - VLLV(07.04.2020 21:10)
- Я бы отказался от упакованных структур вообще. Проблема упакованных
структур, что абсолютно все должны знать, что вот именно эта
структура -- упакованная. А атрибут применяется не к типу данных, а
с переменной. В итоге тот же указатель -- он указывает как бы на
обычную (не упакованную) структуру уже. Либо замучаться везде
писать packed, либо отовсюду убрать, что сильно проще. Ибо вообще
непонятно зачем, создает массу проблем и ничего не решает.
Сериализацию нужно нормально fk0(29 знак., 06.04.2020 17:06)
- Я отказался в новых проектах, а в старых не могу из-за совместимости с ранее выпущенными устройствами. - VLLV(06.04.2020 21:41)
- Разве? Сколько раз использовал Andreas(118 знак., 06.04.2020 17:17)
- В хедере описываете тип: LightElf(137 знак., 07.04.2020 17:52 - 08.04.2020 00:26)
- +1 - Aleksey_75(07.04.2020 17:57)
- Есть очевидная проблема, как например взять адрес члена упакованной
структуры и передать его по-указателю в функцию, например? А никак.
Потому, что член имеет определённый тип со своим свойстом alignas
(в C++, в C тоже, но неявно) и он ничего не знает, про то что
уложен в упакованную структуру. А для работы с членом положенным в
упакованную структуру нужно генерировать совершенно другой код
(из-за "ручного" выравнивания например). fk0(196 знак., 07.04.2020 21:55)
- Да, теперь понял в чем проблема, спасибо. Но до таких высот я пока
не поднимался и члены структур передавал в ф-ции только по
значению, и то редко. ИМХО заполнять заголовок пакета(а зачем еще
упаковка?) надо в одном месте. - Andreas(07.04.2020 22:35)
- Упаковка бывает нужна для уменьшения места в памяти. - VLLV(07.04.2020 22:58)
- вы о членах структуры которые сами являются структурами ? хм!
Принято! Хотя я последнее время поголовно упаковываю - Aleksey_75(07.04.2020 22:08)
- Нет, я даже об обычном int, например. Он же тоже выровнен должен
быть. И если на AVR оно прокатит, то на ARM'е может не проканать. - fk0(07.04.2020 22:18)
- Если долго и упорно стрелять себе в ногу - то рано или поздно
попадешь. Вменяемые люди таки обычно располагают поля структур
сообразно их размеру. - LightElf(07.04.2020 23:05)
- Тогда и упаковка не нужна. - fk0(07.04.2020 23:56)
- Какие альтернативы, например, для такой структуры? LightElf(475 знак., 08.04.2020 00:33)
- Сериализация руками. Вообще адский говнокод, очевидно же, хотя бы
из-за ендианности. Хотя ты конечно выкрутился и int32 у тебя
оказался случайно выровненный. Но если развивать мысль дальше, то и
без прагм оно точно так же разложит. Спрашивается, зачем
"упакованная" структура? - fk0(08.04.2020 01:33, ссылка)
- Но зачем делать руками работу компилятора и/или железа?
Эндианность, очевидно, в IP пакете фиксирована. А в коде, очевидно,
используются стандартные HTONL()/htonl() сотоварищи. Без прагм, в
зависимости от компилятора и целевой платформы, может разложиться
весьма по-разному. С прагмами - единственным определенным образом.
И почему это "случайно выровненный int32"? Вполне себе не случайно,
а вовсе даже прописано в спецификации на драйвер канального уровня.
Для LightElf(95 знак., 08.04.2020 02:37)
- Зачем делать работу... в твоем случае ни за чем. Но в общем случае -- это не решение, а говнокод. - fk0(08.04.2020 11:46)
- Никак по-разному разложиться не может. Разложится всегда именно так
же как и с прагмами. Потому, что иначе не были бы возможны массивы
(alignas == sizeof) если речь идет о типах uint8, uint16, uint32 и
о "ручном" раскладывании с выравниванием, как сделано у тебя. А
если речь о других типах (структуры), или раскладка не выровненная
(int32 не на 32-битной границе), то возникает упомянутая мною
проблема: невозможность использования указателей. Выводы -- прагмы
бесполезны и не fk0(104 знак., 08.04.2020 11:42)
- А ты упертый :) Но блох ты ловишь не там. Разложиться по-другому
может, особенно на архитектурах без 16-битных операций (типа ARMv4)
- компилятор выровняет uint16_t на 32 бита. А вот как раз получить
раскладку с int32 не на 32-битной границе - это надо сильно
постараться. Ну и использование указателей на поля структуры,
вместо указателя на структуру целиком - это путь к успеху. - LightElf(08.04.2020 12:17)
- Отлично. Но ты ж сам доказал, что говнокод. На ARMv4. У тебя там
что лежит за 16-битным значением окажется не выровненным и на него
нельзя будет взять указатель. А сериализация ручками -- она всегда
работает, надежно железобетонно. И использование указателей на поля
структуры -- нормальный способ, иначе как писать абстрактные
функции, а не функции работающие именно с такой структурой. Хотя
конечно скалярные значения нормальные люди возвращают вовсе
по-значению, но случаи они fk0(14 знак., 08.04.2020 13:50)
- Я ж говорю - упертый ты :) В приведенной выше упакованной структуре (стандартном заголовке IP пакета) все поля натурально выровнены. Т.е. uint16_t лежит по смещению, кратному двум, а uint32_t лежит по смещению, кратному четырем. Так задумано изначально не самыми глупыми людьми. Соответственно, если сама структура лежит по адресу кратному четырем, то и все ее поля лежат как положено. И указатели нормально можно брать и использовать. Упаковка нужна, чтобы особо умные LightElf(208 знак., 08.04.2020 16:21)
- Ну есть же возможность объявить указатель __packed, тогда
компилятор знает, что выравнивания нет. - VLLV(08.04.2020 14:55)
- Покажи пальцем где есть, я не в курсе. Всю жизнь упакованными были
только структуры, а не указатель на int. Кроме того, невозможно же
всем функциям присвоить такой атрибут. Есть, например, обычная
функция, которая возвращает значение по-указателю (например,
time(3)) и она ни сном, ни духом, что её аргумент могут положить в
упакованную структуру. - fk0(08.04.2020 15:09)
- Help IAR VLLV(1 знак., 08.04.2020 17:45, картинка)
- У меня ИАР ругается: argument of type "int __packed *" is incompatible with parameter of type "int *" йцyкeн(379 знак., 08.04.2020 15:55)
- А разве компилятор не пожалуется, если взять такой указатель без
явного приведения типов и т.п. трюков? - AlexBi(08.04.2020 15:15)
- Невыровненный доступ компилятор может еще и догадается обыграть, а
вот урезанное поле - уже не обязательно. Помню у меня запись в
упакованную структуру грохала пару соседних полей. Решил отменой
упаковки везде где можно. lloyd(47 знак., 08.04.2020 15:36)
- "Урезанное поле" - это когда пакед и не пакед структура различаются
по размеру? И потом a=b, где а и b структуры с разной паковкой? Мне
кажется пакед и не пакед компилятором считаются разными типами со
всеми вытекающими ошибками на этапе компиляции. - AlexBi(08.04.2020 15:55)
- int:4 - я про такие. - lloyd(08.04.2020 16:00)
- Указатели на битовые поля невозможны. И сами битовы поля такой же
источник граблей как упакованные структуры. Их давно пора выкинуть
из стандарта, а упакованных структур и никогда не было в стандарте,
к слову (по причине массы сопутствующих проблем и невозможности
писать портируемый код). - fk0(08.04.2020 16:20)
- Битовые поля, как и обычные поля в структуре - это эффективный способ систематизации данных. Да, есть недостатки, но цель выполняет. Если дурак наступает на грабли, так что, от использования граблей отказаться? - VLLV(08.04.2020 18:06)
- Поэтому в каждом компиляторе есть свой собственный, уникальный
способ сделать упакованные структуры. Я ж говорю, стандартизаторы -
те еще затейники. Ввести в стандарт мало кому нужный complex.h, но
не ввести стопку элементарных макросов с описанием целевой машины
(типа эндианности, направления роста стека, нативного размера
машинного слова и т.д.). В результате каждый второй Цэ-проект на
гитхабе занимается попытками выяснить сие по косвенным признакам. - LightElf(08.04.2020 16:34)
- Смотря как смотреть. Упакованные структуры -- не нужны. Знать тебе
эндианность, направление роста стека и прочее -- зачем? Если ты
пишешь портируемый код, то ты не должен полагаться на такие знания.
Это нужно только системным программистам в исключительных случаях.
А пытаются применять когда попало, когда не нужно -- и огребают
проблем. Код на другой платформе уже или не скомпилируется, или не
зарабоатет. А complex.h же очевидно нужен в цифровой обработке
сигналов, fk0(9 знак., 08.04.2020 16:55)
- Блин, но системное программирование - это и есть основная область
применения Цэ в дивном новом мире питонов и джаваскриптов. И как
раз для портируемости и надо знать эндианность и все такое прочее.
Прятать голову в песок можно сколько угодно, но вот тебе IP-пакет и
у него строго предопределенная эндианность. Ввели бы один раз в
стандарт что-то вроде GCC-шного __BYTE_ORDER__ - и прекрасно. То же
самое с упакованными структурами/типами. Если бы они не были нужны
- никто бы LightElf(359 знак., 08.04.2020 18:29)
- Вот потому и в стандарт и не вводится. Написанная программа должна
одинаково работать на всех платформах. Почему не стандартизовать --
я ответил, из-за проблемы с указателями на члены структуры.
Касательно ЦОС, я видел, где complex.h использовался. Питон здеь ни
при чём, можно конечно всё то же самое сделать руками, посчитав
синусы и косинусы отдельно, и более того в реализации на целых
числах так и будет, но в обобщённом коде -- вполне себе решение. И
да, системные fk0(209 знак., 08.04.2020 22:17, ссылка)
- чётко сделал сериализатор. По крайней мере мне нравится - megajohn(24.07.2020 09:02)
- За ссыль на онлайн компилер - спасибо. Скомпилил твой сериализатор под MIPS и ARMv5. Байтораздирающее зрелище... - LightElf(09.04.2020 12:49)
- Простой вопрос: если пакованная структура представляет собой
регистры некоторого периферийного блока, что делать будешь? - LightElf(09.04.2020 03:14)
- Ничего делать не буду, не нужно так делать. Это говнокод. Уже массу
раз такое видел: наупаковывают, еще и с битовыми полями, и работает
оно только в этой версии фирменного недокомпилятора. К регистрам
нужно обращаться по адресу, и не нужны там недоструктуры
отсутствующие в стандарте. Достаточно массы дефайнов. - fk0(09.04.2020 03:36)
- *Вздрогнул* Ужос... - LightElf(09.04.2020 12:45)
- Это типа такого? Andreas(478 знак., 09.04.2020 09:26)
- Ничего делать не буду, не нужно так делать. Это говнокод. Уже массу
раз такое видел: наупаковывают, еще и с битовыми полями, и работает
оно только в этой версии фирменного недокомпилятора. К регистрам
нужно обращаться по адресу, и не нужны там недоструктуры
отсутствующие в стандарте. Достаточно массы дефайнов. - fk0(09.04.2020 03:36)
- Вот потому и в стандарт и не вводится. Написанная программа должна
одинаково работать на всех платформах. Почему не стандартизовать --
я ответил, из-за проблемы с указателями на члены структуры.
Касательно ЦОС, я видел, где complex.h использовался. Питон здеь ни
при чём, можно конечно всё то же самое сделать руками, посчитав
синусы и косинусы отдельно, и более того в реализации на целых
числах так и будет, но в обобщённом коде -- вполне себе решение. И
да, системные fk0(209 знак., 08.04.2020 22:17, ссылка)
- Блин, но системное программирование - это и есть основная область
применения Цэ в дивном новом мире питонов и джаваскриптов. И как
раз для портируемости и надо знать эндианность и все такое прочее.
Прятать голову в песок можно сколько угодно, но вот тебе IP-пакет и
у него строго предопределенная эндианность. Ввели бы один раз в
стандарт что-то вроде GCC-шного __BYTE_ORDER__ - и прекрасно. То же
самое с упакованными структурами/типами. Если бы они не были нужны
- никто бы LightElf(359 знак., 08.04.2020 18:29)
- Смотря как смотреть. Упакованные структуры -- не нужны. Знать тебе
эндианность, направление роста стека и прочее -- зачем? Если ты
пишешь портируемый код, то ты не должен полагаться на такие знания.
Это нужно только системным программистам в исключительных случаях.
А пытаются применять когда попало, когда не нужно -- и огребают
проблем. Код на другой платформе уже или не скомпилируется, или не
зарабоатет. А complex.h же очевидно нужен в цифровой обработке
сигналов, fk0(9 знак., 08.04.2020 16:55)
- Указатели на битовые поля невозможны. И сами битовы поля такой же
источник граблей как упакованные структуры. Их давно пора выкинуть
из стандарта, а упакованных структур и никогда не было в стандарте,
к слову (по причине массы сопутствующих проблем и невозможности
писать портируемый код). - fk0(08.04.2020 16:20)
- int:4 - я про такие. - lloyd(08.04.2020 16:00)
- "Урезанное поле" - это когда пакед и не пакед структура различаются
по размеру? И потом a=b, где а и b структуры с разной паковкой? Мне
кажется пакед и не пакед компилятором считаются разными типами со
всеми вытекающими ошибками на этапе компиляции. - AlexBi(08.04.2020 15:55)
- Невыровненный доступ компилятор может еще и догадается обыграть, а
вот урезанное поле - уже не обязательно. Помню у меня запись в
упакованную структуру грохала пару соседних полей. Решил отменой
упаковки везде где можно. lloyd(47 знак., 08.04.2020 15:36)
- Покажи пальцем где есть, я не в курсе. Всю жизнь упакованными были
только структуры, а не указатель на int. Кроме того, невозможно же
всем функциям присвоить такой атрибут. Есть, например, обычная
функция, которая возвращает значение по-указателю (например,
time(3)) и она ни сном, ни духом, что её аргумент могут положить в
упакованную структуру. - fk0(08.04.2020 15:09)
- Отлично. Но ты ж сам доказал, что говнокод. На ARMv4. У тебя там
что лежит за 16-битным значением окажется не выровненным и на него
нельзя будет взять указатель. А сериализация ручками -- она всегда
работает, надежно железобетонно. И использование указателей на поля
структуры -- нормальный способ, иначе как писать абстрактные
функции, а не функции работающие именно с такой структурой. Хотя
конечно скалярные значения нормальные люди возвращают вовсе
по-значению, но случаи они fk0(14 знак., 08.04.2020 13:50)
- А ты упертый :) Но блох ты ловишь не там. Разложиться по-другому
может, особенно на архитектурах без 16-битных операций (типа ARMv4)
- компилятор выровняет uint16_t на 32 бита. А вот как раз получить
раскладку с int32 не на 32-битной границе - это надо сильно
постараться. Ну и использование указателей на поля структуры,
вместо указателя на структуру целиком - это путь к успеху. - LightElf(08.04.2020 12:17)
- Но зачем делать руками работу компилятора и/или железа?
Эндианность, очевидно, в IP пакете фиксирована. А в коде, очевидно,
используются стандартные HTONL()/htonl() сотоварищи. Без прагм, в
зависимости от компилятора и целевой платформы, может разложиться
весьма по-разному. С прагмами - единственным определенным образом.
И почему это "случайно выровненный int32"? Вполне себе не случайно,
а вовсе даже прописано в спецификации на драйвер канального уровня.
Для LightElf(95 знак., 08.04.2020 02:37)
- Сериализация руками. Вообще адский говнокод, очевидно же, хотя бы
из-за ендианности. Хотя ты конечно выкрутился и int32 у тебя
оказался случайно выровненный. Но если развивать мысль дальше, то и
без прагм оно точно так же разложит. Спрашивается, зачем
"упакованная" структура? - fk0(08.04.2020 01:33, ссылка)
- Какие альтернативы, например, для такой структуры? LightElf(475 знак., 08.04.2020 00:33)
- Тогда и упаковка не нужна. - fk0(07.04.2020 23:56)
- вот сейчас прям смотрю , передаю в функцию член структуры массив uint8_t все четко, никаких траблов не испытываю - Aleksey_75(07.04.2020 22:26)
- Если долго и упорно стрелять себе в ногу - то рано или поздно
попадешь. Вменяемые люди таки обычно располагают поля структур
сообразно их размеру. - LightElf(07.04.2020 23:05)
- Нет, я даже об обычном int, например. Он же тоже выровнен должен
быть. И если на AVR оно прокатит, то на ARM'е может не проканать. - fk0(07.04.2020 22:18)
- Да, теперь понял в чем проблема, спасибо. Но до таких высот я пока
не поднимался и члены структур передавал в ф-ции только по
значению, и то редко. ИМХО заполнять заголовок пакета(а зачем еще
упаковка?) надо в одном месте. - Andreas(07.04.2020 22:35)
- У меня не gcc, а IAR, а там грабли еще те ... The #pragma pack
directive affects declarations of structures following the pragma
directive to the next #pragma pack or the end of the compilation unit. - VLLV(06.04.2020 21:45)
- Я в Иаре пишу как в предыдущем посте. Все Ок при любой оптимизации,
на любых кортексах . Портировал проект в ЖЦЦ, тоже все нормально - IBAH(07.04.2020 18:02)
- Еще раз поясняю. Была забыта pragma(pop) для другой структуры в другом файле, в
результате совершенно другая структура в одном файле считалась
упакованной, а в другом нет. Pragma pack содержит потенциальную
угрозу забыть отменить упаковку, что и произошло. - VLLV(07.04.2020 20:07)
- Я в подобных случаях делаю специальную синтаксическую ошибку, и запускаю на компиляцию. Или шерстить через поиск по файлам проекта - IBAH(07.04.2020 20:58)
- Я тоже на это натыкался, именно поэтому перешел на typedef PACKED_STRUCT - это нагляднее, да еще для разных компилеров можно переопределить. - Andreas(07.04.2020 20:11)
- Еще раз поясняю. Была забыта pragma(pop) для другой структуры в другом файле, в
результате совершенно другая структура в одном файле считалась
упакованной, а в другом нет. Pragma pack содержит потенциальную
угрозу забыть отменить упаковку, что и произошло. - VLLV(07.04.2020 20:07)
- Например в BLE стеке от NXP, который только для IAR полно подобного Andreas(265 знак., 07.04.2020 09:55)
- Я про прагму - именно в ней (нечетном количестве в предыдущем
хедере) была проблема. Если оставлять упаковку, то нужно переходить
на __packed. - VLLV(07.04.2020 17:21)
- Обкладывайте прагмами каждую структуру персонально. Так проще. - LightElf(07.04.2020 20:59)
- lwip использует упаковку структур повсеместно. Там это всё
завёрнуто в сколько-то слоёв, чтобы на любом компиляторе могло
работать. SciFi(625 знак., 07.04.2020 10:08, ссылка)
- Я бы не назвал lwip образцом хорошего кода... Но тут не проблема lwip, проблема в ущербности (всмысле невыразительности) Си как языка - lloyd(07.04.2020 10:20)
- За struct вместо typedef struct эцих с гвоздями. Я обычно еще в
конец заголовка uint8_t data[0] добавляю. И размер заголовка не
ползет и к данным удобно обращаться. - Andreas(07.04.2020 10:16)
- Посадите весь Linux Kernel в этот самый эцих - lloyd(07.04.2020 10:48, ссылка)
- Не хотите - не кушайте. Я же не заставляю. А мне нравится. - SciFi(07.04.2020 10:21)
- Я про прагму - именно в ней (нечетном количестве в предыдущем
хедере) была проблема. Если оставлять упаковку, то нужно переходить
на __packed. - VLLV(07.04.2020 17:21)
- Я в Иаре пишу как в предыдущем посте. Все Ок при любой оптимизации,
на любых кортексах . Портировал проект в ЖЦЦ, тоже все нормально - IBAH(07.04.2020 18:02)
- В хедере описываете тип: LightElf(137 знак., 07.04.2020 17:52 - 08.04.2020 00:26)
- Вроде бы про упаковку теория молчит. То есть это это нестандартное расширение, и наличие глюков в слабо протестированных сценариях не должно удивлять. Может, лучше код показать? - SciFi(06.04.2020 15:19)
- А структуры объявлены через typedef или непосредственно? - IBAH(07.04.2020 21:03)