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

 
 
 
Reply to this topicStart new topic
> Работа с упакованными структурами (Си, ARM9)
Harvester
сообщение Nov 13 2013, 08:23
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 338
Регистрация: 1-02-06
Из: Королев, М.О.
Пользователь №: 13 846



ARM9, компилятор ADS 1.2

Имеется упакованная структура, которая приходит/уходит по интерфейсу, т.е. от упаковки никуда не деться.
Код
typedef __packed struct {
  uint16    params_len;
  uint8     params_data[PARAMS_MAX_SIZE];
  uint16    in_data_len;
  uint16    out_data_len;
} pkt_type;

При передаче в функию указателя как на поле структуры
Код
send_req(..., &input_pkt.params_data[0])

так и на саму структуру
Код
memset(&input_pkt, 0, PACKET_SIZE)

компилятор выдает ошибку
Error: C2906E: <argument x to 'xxxxx'>: implicit cast of pointer loses '__packed' qualifier
Т.е. при взятии адреса упакованной структуры или ее элемента упаковка не учитывается. sad.gif

Как можно обойти такое поведение компилятора?
Я пока вижу только такой выход:
Определить массив
Код
uint8 raw_packet[PACKET_SIZE];

набор констант
Код
#define PARAMS_LEN_OFS   0
#define PARAMS_LEN_TYPE  uint16
...

и обращаться к массиву
Код
params_len = (PARAMS_LEN_TYPE)raw_packet[PARAMS_LEN_OFS];


Может есть более изящное решение?

UPD:
При явном преобразвании к char *
Код
memset((char *)&input_pkt, 0, PACKET_SIZE)

ошибка пропадает

Сообщение отредактировал Harvester - Nov 13 2013, 09:32


--------------------
-Да как так-то?/-Да как-то так/-Ну так-то да
Go to the top of the page
 
+Quote Post
_pv
сообщение Nov 13 2013, 08:45
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(Harvester @ Nov 13 2013, 15:23) *
Я пока вижу только такой выход:
Определить массив
Код
uint8 raw_packet[PACKET_SIZE];

набор констант
Код
#define PARAMS_LEN_OFS   0
#define PARAMS_LEN_TYPE  uint16
...

и обращаться к массиву
Код
params_len = (PARAMS_LEN_TYPE)raw_packet[PARAMS_LEN_OFS];

Может есть более изящное решение?

это не правильно, надо
Код
params_len = *(PARAMS_LEN_TYPE *) &raw_packet[PARAMS_LEN_OFS];

иначе он 16 бит из 8ми разрядного raw_packet[PARAMS_LEN_OFS] не достанет.
при этом, не знаю догадается ли компилятор что адреса могут быть не выровнены.

можно в макрос завернуть, который еще и endianess может менять если надо.
но за типами данных самому следить тогда надо.
#define UNPACK16(buff,offset) ((u16)buff[offset] + (u16)buff[offset+1] << 8)
params_len = UNPACK16(raw_packet,PARAMS_LEN_OFS);

Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 13 2013, 10:37
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Harvester @ Nov 13 2013, 12:23) *
При явном преобразвании к char *
Код
memset((char *)&input_pkt, 0, PACKET_SIZE)

ошибка пропадает

Это и есть более изящное решение: использовать явное преобразование типа там, где структура нужна не в виде структуры, а в виде последовательности байтов (тот же memset, прием/передача по интерфейсу).
Go to the top of the page
 
+Quote Post
Harvester
сообщение Nov 13 2013, 10:54
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 338
Регистрация: 1-02-06
Из: Королев, М.О.
Пользователь №: 13 846



Цитата(aaarrr @ Nov 13 2013, 14:37) *
Это и есть более изящное решение: использовать явное преобразование типа ...

Тогда уже теоретический вопрос: почему явное преобразование годится, а неявное - генерирует ошибку?
У memset тип 1-го параметра вообще void * (внутри функции он приводится к char *). Мне всегда казалось, что применение void подразумевает автоматическую совместимость с любым типом.


--------------------
-Да как так-то?/-Да как-то так/-Ну так-то да
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 13 2013, 11:13
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Наверное, таково видение создателей компилятора - напоминать при любом неявном преобразовании упакованного типа. Все же это надстройка.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Nov 13 2013, 11:30
Сообщение #6


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Или недоработка. Но, возможно, ошибка - выдавать Error при присваивании типу void * адреса из того же пространства, но с атрибутом внутреннего/внешнего выравнивания. Явным преобразованием можно по ошибке отключить ключевые квалификаторы адресного пространства или типа доступа, вроде volatile, __code, __data и прочие платформозависимые.

Сообщение отредактировал GetSmart - Nov 13 2013, 17:34


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 02:31
Рейтинг@Mail.ru


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