|
|
|
*char to long, получение long из массива char |
|
|
|
Nov 27 2017, 06:10
|
Местный
Группа: Свой
Сообщений: 327
Регистрация: 30-10-05
Пользователь №: 10 288
|
Цитата(juvf @ Nov 27 2017, 08:42) Нужно из массива байт получить int, long, float, uint32_t и т.п. Явное приведение типов не всегда и не везде работает из-за "выравнивания". А какой компилятор не поддерживает #pragma pack ? Цитата(juvf @ Nov 27 2017, 08:42) Наверняка есть либо в std, либое ещё где уже готовые методы/шаблоны. Или уже кем-то ураденно написано... только нужно знать, где это взять. Кто-нибудь может подсказать? Копайте в сторону endianess - оно на это более чем завязано.
|
|
|
|
|
Nov 27 2017, 09:25
|
Знающий
Группа: Участник
Сообщений: 750
Регистрация: 1-11-11
Пользователь №: 68 088
|
Цитата(juvf @ Nov 27 2017, 08:42) Нужно из массива байт получить int, long, float, uint32_t и т.п. Явное приведение типов не всегда и не везде работает из-за "выравнивания". Какое ещё выравнивание, если у вас массив байт? Код uint32_t p = *(uint32_t*)&array[7];
--------------------
"... часами я мог наблюдать, как люди работают." (М. Горький)
|
|
|
|
|
Nov 27 2017, 09:28
|
Знающий
Группа: Участник
Сообщений: 518
Регистрация: 29-09-11
Пользователь №: 67 450
|
Цитата(gerber @ Nov 27 2017, 13:25) Какое ещё выравнивание, если у вас массив байт? Код uint32_t p = *(uint32_t*)&array[7]; Многие процессоры требуют выравнивания 4-байтовых целых по адресу, кратному 4, 2-байтовых - кратному 2, float и double - 4 и 8 соответственно. Там такое выражение может привести к срабатыванию системного прерывания и вылету из программы. А может не привести (как повезет с адресами).
|
|
|
|
|
Nov 27 2017, 10:22
|
Знающий
Группа: Участник
Сообщений: 750
Регистрация: 1-11-11
Пользователь №: 68 088
|
Сторона, передающая разнородные данные, упаковывает (сериализует) их в байтовый поток сообразно своим установкам - endiannes, align, pack и т. п. Возможно, что округление смещения полей uint32_t до 4-х уже учтено при формировании структуры пакета, и это было бы наиболее грамотным решением. В любом случае, вам должен быть известен алгоритм сериализации. Вы пишете десериализацию байтового потока обратно в разнородные данные на известном вам процессоре - вам и карты (описание потока) в руки. Если офсеты полей uint32_t кратны 4 - то достаточно приведения типа указателя, если нет - придется городить десериализацию. В любом случае, универсального решения тут не будет, даже в случае memcpy() можно напороться на разный endiannes и т. д.
--------------------
"... часами я мог наблюдать, как люди работают." (М. Горький)
|
|
|
|
|
Nov 27 2017, 11:20
|
Профессионал
Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045
|
Сторона, передающая разнородные данные, упаковывает (сериализует) их в байтовый поток сообразно своим установкам строго в соответствии с протоколом передачи данных. Протокол абстрагирован от архитектуры (например Modbus). Мне известен алгоритм упаковки. Думаю memcpy - лучшее решение, только всё таки оберну в шаблон, чтоб сырц был компактнее. Я думал, может уже есть компактное решение. А про endianess..... - на пк использую QtEndianess<>, для мк пока не было нужды. В интернетах пишут, есть макросы для endianess, нешел в #include < linux/kernel.h >, но это линукс. а в маздае? а в МК? в std нечем перевернуть ((
|
|
|
|
|
Nov 27 2017, 12:16
|
Местный
Группа: Участник
Сообщений: 319
Регистрация: 27-09-07
Пользователь №: 30 877
|
Цитата(ViKo @ Nov 27 2017, 09:57) А union для чего созданы? С ними уж точно проблем с выравниванием быть не должно. +1 . только юнион надо делать с упаковкой в 1 байт, иначе будет больно
|
|
|
|
|
Jan 28 2018, 19:16
|
Участник
Группа: Участник
Сообщений: 20
Регистрация: 18-03-12
Пользователь №: 70 865
|
Цитата(juvf @ Nov 27 2017, 08:42) uint32_t p = (uint32_t)array[7]; p |= (uint32_t)array[8] << 8; p |= (uint32_t)array[9] << 16; p |= (uint32_t)array[10] << 24;
Наверняка есть либо в std, либое ещё где уже готовые методы/шаблоны. Или уже кем-то ураденно написано... только нужно знать, где это взять. Кто-нибудь может подсказать? Это нормальный код для этой задачи. Использовать инлайн функции совершенно нормальная практика для подобных целей, например можете сделать так же как в этом примере https://github.com/threatstack/libldns/blob...s/util.h.in#L81Использовать набор функций ldns_read_uint32, ldns_read_uint16, ldns_read_uint8 для знаковых соотвественно.
|
|
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|