MrYuran 27 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба On 10/19/2023 at 8:56 AM, Arlleex said: Вы щас серьезно?😆 А как быть с тем, что уже сделано предыдущим поколение разработчиков, причем, буквально повсюду? По хорошему, переделать. Но если нравится работа сапера (хотя скорее ассенизатора), то можно оставить как есть Да, бывает, что лучше его (код, а вы что подумали) палочкой не ковырять. Чтоб не воняло. Пусть кто-нибудь другой вляпается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба #ifndef UNALIGNED_H__ #define UNALIGNED_H__ template<typename T> struct unaligned { operator T() const { return Data; } void operator =(T const & value) { Data = value; } T Data; } __attribute__((packed)); #endif // UNALIGNED_H__ Объявить данные как unaligned<uint16_t>, unaligned<int32_t>, unaligned<что угодно> и делать с ними что угодно. В том числе и работать с указателями на unaligned<что угодно>. Но это плюсы, да. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 62 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба On 10/19/2023 at 9:55 AM, MrYuran said: По хорошему, переделать. Но если нравится работа сапера (хотя скорее ассенизатора), то можно оставить как есть А как быть с протоколами Ethernet и всем тем, что работает поверх него ? А с Modbus ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 27 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба On 10/19/2023 at 10:01 AM, dimka76 said: А как быть с протоколами Ethernet и всем тем, что работает поверх него ? А с Modbus ? А что с ними не так? Модбас так по умолчанию имеет регистры uint16_t, выравнивай-не хочу. а входной поток сливается в байтовый буфер и затем парсится в какой-нибудь uint16_t InputRegisters[NumOf] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба 55 минут назад, MrYuran сказал: А что с ними не так? Модбас так по умолчанию имеет регистры uint16_t, выравнивай-не хочу. а входной поток сливается в байтовый буфер и затем парсится в какой-нибудь uint16_t InputRegisters[NumOf] Ну так то в Modbus не все 16-битное: slave ID, код функции и т.д. - байтовые. И структуру "подгонять" под данные не получится. В Ethernet, да и вообще в любых интерфейсах и протоколах (не только сетевых) сериализация и упаковка данных имеет важное значение: скорость передачи и детерминированность при взаимодействии различных архитектур. Как раз костыльный способ - это пытаться натянуть на некий набор упорядоченных данных какую-то там структуру, чтобы в ней не было паддингов для какой-то конкретной архитекруры CPU. 1 час назад, Сергей Борщ сказал: Но это плюсы, да. А что делать Си-шникам? Получается, в GCC нет специального ключевого слова для обозначения невыровненного доступа? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tonyk_av 44 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба 56 minutes ago, MrYuran said: Модбас так по умолчанию имеет регистры uint16_t, выравнивай-не хочу Нифига подобного. Есть команды работы с битовыми объектами, есть работа с файлами. Там идёт работа именно с байтами. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 27 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба On 10/19/2023 at 11:07 AM, Arlleex said: Как раз костыльный способ - это пытаться натянуть на некий набор упорядоченных данных какую-то там структуру, чтобы в ней не было паддингов для какой-то конкретной архитекруры CPU. А мапить структуру на фрейм - вообще последнее дело. Сугубо мое личное мнение, основанное на печальном опыте Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ivan. 4 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба 3 часа назад, MrYuran сказал: Вообще нормальная практика предполагает все-таки выравнивание в структурах. Я бы рад, да не от меня зависит. Когда это пакет данных, передаваемый по какому либо интерфейсу - приходится подстраиваться. А защитить себя хочется. 14 часов назад, arhiv6 сказал: В cmsis_gcc.h есть макрос __UNALIGNED_UINT32(x) : Интересное решение, правда не совсем то, что я хотел, но если его немного развить то получается следующее: //Упакованная структура struct Foo { uint8_t v1 = 1; uint16_t v2 = 2; const uint16_t v3 = 3; struct { int v4; } bar; } __attribute__((packed)); Foo foo; //Вспомогательный класс template<typename T> struct Unaligned { struct Packed { Packed() = default; Packed &operator = (const T &value) {v = value; return *this;} operator T () const {return v;} // T *operator ->() {return &v;} // const T *operator ->() const {return &v;} protected: T v; } __attribute__((packed)); constexpr Unaligned(T *ptr): ptr((Packed*)ptr) {} Packed &operator * () const {return *ptr;} Packed &operator ->() const {return *ptr;} Packed &operator [](unsigned index) const {return ptr[index];} protected: Packed *ptr; }; //Функция создания объекта Unaligned template<typename T> auto unaligned(T *ptr) {return Unaligned<T>(ptr);} //Функция принимающая unaligned указатель void func(Unaligned<uint16_t> array) { array[0] = 40; } //Пример использования auto vPtr = unaligned(&foo.v2); //создание unaligned указателя v = *vPtr + vPtr[0]; //Чтение данных по указателю или элемента массива //Запись различными способами *vPtr = 10; vPtr[0] = 20; *unaligned(&foo.v2) = 30; //Попытка записать в константу *unaligned(&foo.v3) = 40; //error: assignment of read-only member 'Unaligned<const short unsigned int>::Packed::v' //А вот это пока не могу решить unaligned(&foo.bar)->v4 = 50; //Передача невыровненного указателя в функцию typedef void (*Func)(Unaligned<uint16_t> array); Func f = &func; f(&foo.v2); Теперь появляется следующий вопрос, как побороться с предупреждением компилятора при вызове конструктора? warning: taking address of packed member of 'Foo' may result in an unaligned pointer value [-Waddress-of-packed-member] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба 46 минут назад, MrYuran сказал: А мапить структуру на фрейм - вообще последнее дело. Почему? Для Ethernet - это самый оптимальный путь. Да и для USB частенько. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба 19 минут назад, MrYuran сказал: А мапить структуру на фрейм - вообще последнее дело. Вполне себе нормальное решение, которое подойдет абсолютно всем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 78 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба 1 hour ago, Arlleex said: 2 hours ago, Сергей Борщ said: Но это плюсы, да. А что делать Си-шникам? точно так же заворачивать memcpy в макросы 🙂 2 hours ago, dimka76 said: А как быть с протоколами Ethernet не пытаться запихивать сетевые протоколы в упакованые структуры Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба 3 минуты назад, _pv сказал: не пытаться запихивать сетевые протоколы в упакованые структуры Ваше предложение? Они уже туда запихнуты RFC. Как предлагаете это решать? 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба 12 минут назад, Ivan. сказал: Теперь появляется следующий вопрос, как побороться с предупреждением компилятора при вызове конструктора? warning: taking address of packed member of 'Foo' may result in an unaligned pointer value [-Waddress-of-packed-member] Так значит пришли к тому, от чего уходили - т.е. не решили вопрос, а лишь дописали кучу плюсовых наворотов Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ivan. 4 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба 8 минут назад, Arlleex сказал: Так значит пришли к тому, от чего уходили - т.е. не решили вопрос, а лишь дописали кучу плюсовых наворотов Пока я развивал идею - вы тут много о чем пообщались и, кстати, пришли к похожему решению. А во вторых я так и сказал, что это не совсем то, но интересная идея Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 19 октября, 2023 Опубликовано 19 октября, 2023 · Жалоба 1 час назад, Ivan. сказал: А во вторых я так и сказал, что это не совсем то, но интересная идея Осталось только посмотреть: в какой код выливается эта "интересная идея"? А то может оказаться (по факту) совсем не интересной... Без всяких плюсов должно работать тривиальное: #pragma pack(push, 1) struct PackU64 { u64 d64; }; #pragma pack(pop) struct Qqq { u8 x1; PackU64 x2; }; Qqq volatile qqq; u32 volatile z; void F1(void volatile *p) { u64 q = ((PackU64 volatile *)p)->d64; z = q; z = q >> 32; } int main() { z = qqq.x1; F1((void volatile *)&qqq.x2); return 0; } Проверяем - компилим "gcc 9.2.1 20191025". Получаем: 20 _Z2F1PVv: 21 .fnstart 22 .LFB0: 23 @ args = 0, pretend = 0, frame = 0 24 @ frame_needed = 0, uses_anonymous_args = 0 25 @ link register save eliminated. 26 0000 0168 ldr r1, [r0] @ unaligned 27 0002 024B ldr r3, .L2 28 0004 4268 ldr r2, [r0, #4] @ unaligned 29 0006 1960 str r1, [r3] 30 0008 1A60 str r2, [r3] 31 000a 7047 bx lr Т.е. - всё ок: для чтения qqq.x2 использованы команды, допускающие невыровненные обращения (2шт. LDR). Для проверки комментируем строки: //#pragma pack(push, 1) ... //#pragma pack(pop) Компилим, получаем: 20 _Z2F1PVv: 21 .fnstart 22 .LFB0: 23 @ args = 0, pretend = 0, frame = 0 24 @ frame_needed = 0, uses_anonymous_args = 0 25 @ link register save eliminated. 26 0000 D0E90001 ldrd r0, [r0] 27 0004 014B ldr r3, .L2 28 0006 1860 str r0, [r3] 29 0008 1960 str r1, [r3] 30 000a 7047 bx lr И убеждаемся, что метод работает: Для чтения qqq.x2 теперь компилятор использовал LDRD (так как он считает, что qqq.x2 выровнена). Как видно - никаких варнингов (при взятии указателя) нет. Всё как хотел ТС. И без всяких ненужных плюсовых наворотов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться