реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> *char to long, получение long из массива char
juvf
сообщение Nov 27 2017, 05:42
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Нужно из массива байт получить int, long, float, uint32_t и т.п. Явное приведение типов не всегда и не везде работает из-за "выравнивания".

писать китайский код типа

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, либое ещё где уже готовые методы/шаблоны. Или уже кем-то ураденно написано... только нужно знать, где это взять. Кто-нибудь может подсказать?
Go to the top of the page
 
+Quote Post
gosha-z
сообщение Nov 27 2017, 06:10
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 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 - оно на это более чем завязано.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Nov 27 2017, 06:57
Сообщение #3


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



А union для чего созданы? С ними уж точно проблем с выравниванием быть не должно.
Go to the top of the page
 
+Quote Post
novikovfb
сообщение Nov 27 2017, 07:09
Сообщение #4


Знающий
****

Группа: Участник
Сообщений: 518
Регистрация: 29-09-11
Пользователь №: 67 450



Цитата(juvf @ Nov 27 2017, 09:42) *
Нужно из массива байт получить int, long, float, uint32_t и т.п. Явное приведение типов не всегда и не везде работает из-за "выравнивания".

если с порядком старший/младший расхождений нет, можно использовать memcpy(&p,array+7,sizeof(p));
Go to the top of the page
 
+Quote Post
juvf
сообщение Nov 27 2017, 07:12
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(ViKo @ Nov 27 2017, 11:57) *
А union для чего созданы? С ними уж точно проблем с выравниванием быть не должно.
юнион для другого созданы, тут они не уместны. пришел по уарту массив байт. где-то в массиве лежат uint32_t, где-то float.... нужно из произвольного адреса получить многобайтовые переменные.
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Nov 27 2017, 08:29
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Вариант описанный novikovfb самый правильный с точки зрения стандарта. При желании можно обернуть в несложный шаблон. Стандартного способа не припомню.
Go to the top of the page
 
+Quote Post
gerber
сообщение Nov 27 2017, 09:25
Сообщение #7


Знающий
****

Группа: Участник
Сообщений: 750
Регистрация: 1-11-11
Пользователь №: 68 088



Цитата(juvf @ Nov 27 2017, 08:42) *
Нужно из массива байт получить int, long, float, uint32_t и т.п. Явное приведение типов не всегда и не везде работает из-за "выравнивания".

Какое ещё выравнивание, если у вас массив байт? rolleyes.gif
Код
uint32_t p = *(uint32_t*)&array[7];


--------------------
"... часами я мог наблюдать, как люди работают." (М. Горький)
Go to the top of the page
 
+Quote Post
novikovfb
сообщение Nov 27 2017, 09:28
Сообщение #8


Знающий
****

Группа: Участник
Сообщений: 518
Регистрация: 29-09-11
Пользователь №: 67 450



Цитата(gerber @ Nov 27 2017, 13:25) *
Какое ещё выравнивание, если у вас массив байт? rolleyes.gif
Код
uint32_t p = *(uint32_t*)&array[7];

Многие процессоры требуют выравнивания 4-байтовых целых по адресу, кратному 4, 2-байтовых - кратному 2, float и double - 4 и 8 соответственно. Там такое выражение может привести к срабатыванию системного прерывания и вылету из программы. А может не привести (как повезет с адресами).
Go to the top of the page
 
+Quote Post
juvf
сообщение Nov 27 2017, 09:39
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(gerber @ Nov 27 2017, 14:25) *
Какое ещё выравнивание, если у вас массив байт? rolleyes.gif
Код
uint32_t p = *(uint32_t*)&array[7];

может быть так, что процессор обращается к адресам кратно 4. т.е. из uint32_t p = *(uint32_t*)&array[7]; он сделает uint32_t p = *(uint32_t*)&array[4];
Go to the top of the page
 
+Quote Post
gerber
сообщение Nov 27 2017, 10:22
Сообщение #10


Знающий
****

Группа: Участник
Сообщений: 750
Регистрация: 1-11-11
Пользователь №: 68 088



Сторона, передающая разнородные данные, упаковывает (сериализует) их в байтовый поток сообразно своим установкам - endiannes, align, pack и т. п. Возможно, что округление смещения полей uint32_t до 4-х уже учтено при формировании структуры пакета, и это было бы наиболее грамотным решением. В любом случае, вам должен быть известен алгоритм сериализации.
Вы пишете десериализацию байтового потока обратно в разнородные данные на известном вам процессоре - вам и карты (описание потока) в руки. Если офсеты полей uint32_t кратны 4 - то достаточно приведения типа указателя, если нет - придется городить десериализацию.
В любом случае, универсального решения тут не будет, даже в случае memcpy() можно напороться на разный endiannes и т. д.


--------------------
"... часами я мог наблюдать, как люди работают." (М. Горький)
Go to the top of the page
 
+Quote Post
juvf
сообщение Nov 27 2017, 11:20
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Сторона, передающая разнородные данные, упаковывает (сериализует) их в байтовый поток сообразно своим установкам строго в соответствии с протоколом передачи данных. Протокол абстрагирован от архитектуры (например Modbus). Мне известен алгоритм упаковки. Думаю memcpy - лучшее решение, только всё таки оберну в шаблон, чтоб сырц был компактнее. Я думал, может уже есть компактное решение.
А про endianess..... - на пк использую QtEndianess<>, для мк пока не было нужды. В интернетах пишут, есть макросы для endianess, нешел в #include < linux/kernel.h >, но это линукс. а в маздае? а в МК? в std нечем перевернуть ((
Go to the top of the page
 
+Quote Post
AlexRayne
сообщение Nov 27 2017, 12:16
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 27-09-07
Пользователь №: 30 877



Цитата(ViKo @ Nov 27 2017, 09:57) *
А union для чего созданы? С ними уж точно проблем с выравниванием быть не должно.

+1 .
только юнион надо делать с упаковкой в 1 байт, иначе будет больно
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Nov 27 2017, 12:41
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(juvf @ Nov 27 2017, 14:20) *
А про endianess..... - на пк использую QtEndianess<>, для мк пока не было нужды. В интернетах пишут, есть макросы для endianess, нешел в #include < linux/kernel.h >, но это линукс. а в маздае? а в МК? в std нечем перевернуть ((
Передавайте всегда в сетевом порядке. В передатчике и приёмнике используйте htonl/ntohl, htons/ntohs.
Порядок байтов
Go to the top of the page
 
+Quote Post
alx.bilous
сообщение Jan 28 2018, 19:16
Сообщение #14


Участник
*

Группа: Участник
Сообщений: 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 для знаковых соотвественно.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение May 2 2018, 20:19
Сообщение #15


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Посмотрите файлик modbus-data.c из библиотеки libmodbus.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 16th April 2024 - 07:20
Рейтинг@Mail.ru


Страница сгенерированна за 0.01564 секунд с 7
ELECTRONIX ©2004-2016