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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> iar struct union как указать смещение?
AndryG
сообщение Feb 14 2015, 20:10
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 139
Регистрация: 23-05-05
Из: UA
Пользователь №: 5 317



Имеем, для примера, вот такой тип данных, в котором хотим обеспечить к массиву данных доступ к нужным полям по разному "подходу".

Код
typedef union{
  uint8_t raw[4]; // head, bodyA, bodyB, tail
  struct{
    uint8_t b;
  } body;
  uint8_t bodyA;
  uint8_t tail;
} my_t


Понятно, что всё работает неверно. Вопрос: возможно ли указать полям дополнительно смещение? Если да, то как ?

Совет "расположи поля в объединении в нужном порядке" не предлагать. Это лишь пример для обяъснения проблемы. В моем случае необходимо именно указать смещение.

Единственный вариант вижу в объявлении дополнительным полей-проставок, которые будут смещать на нужное место поля. Но и то сработает не везде.
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Feb 15 2015, 10:28
Сообщение #2


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(AndryG @ Feb 14 2015, 23:10) *
...Понятно, что всё работает неверно....


Вы знаете, похоже Вы первый столкнулись с озвученной проблемой за десятилетия существования языка си. Наверное до Вас все были идиотами и лепили костыли.

Вам самому не смешно?

Опишите почему вам понятно "что работает неверно". Конкретнее только. Можно с примерами, начиная от начала файла и заканчивая последней строчкой... А то вырванная из контекста структура - ни о чём...

ЗЫ
Надеюсь аспекты выравнивания данных Вами изучены и в дальнейшем на азы языка мы не свалимся?
Go to the top of the page
 
+Quote Post
SSerge
сообщение Feb 15 2015, 10:45
Сообщение #3


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

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Цитата(AndryG @ Feb 15 2015, 03:10) *
Вопрос: возможно ли указать полям дополнительно смещение? Если да, то как ?

Каким полям?
Если в union, так это невозможно, у объединений это смещение для всех его элементов равно нулю по определению.
Объединения (union) для того и придуманы, а иначе они превратятся в структуры.


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
megajohn
сообщение Feb 15 2015, 17:58
Сообщение #4


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

Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143



Цитата(AndryG @ Feb 14 2015, 23:10) *
Понятно, что всё работает неверно. Вопрос: возможно ли указать полям дополнительно смещение? Если да, то как ?


а чем так не устраивает ?
ссылка


--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
Go to the top of the page
 
+Quote Post
AndryG
сообщение Feb 15 2015, 19:11
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 139
Регистрация: 23-05-05
Из: UA
Пользователь №: 5 317



Цитата
Опишите почему вам понятно "что работает неверно".


my_t.body.b ссылается на байт "bodyA" (см. коммент raw[]), а по смыслу должно на "bodyB"
my_t.bodyA ссылается на "head", а ожидается (из названия) на второй байт "bodyA"
my_t.tail ссылается на "head", а ожидается (из названия) на четвертый байт "tail"

megajohn, в вашем примере t.s.body.b = 2; t.s.bodyA = 3 неверно ссылаются.


У меня есть массив данных. Одна функция работает со всем массивом data[].
Второй функции интересны в этом массиве только некоторые участки (первый, пятый, девятый-десятый байты, для примера)
Третья должна видеть этот массив сосвсем иначе...
Вот я и хочу сделать объединение:
Код
union{
  raw[10]
  v1: struct{
    b1 -- указывает на верное место
    b5 -- указывает на второй байт, а хочется на пятый
    w5-- указывает на третий байт, а хочется на девятый
  }
}

Другими словами, я хочу указать полю структуры адрес (относительно его головы).

SSerge с превращением объединения в структуру это вы верно подметили sm.gif

Раз звучат только уточняющие вопросы, значит я слишком много хочу...

Go to the top of the page
 
+Quote Post
SSerge
сообщение Feb 15 2015, 20:08
Сообщение #6


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

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Код
typedef union{
  uint8_t raw[4]; // head, bodyA, bodyB, tail
  struct{
    uint8_t head;
    uint8_t bodyA;
    uint8_t bodyB;
    uint8_t tail;
  } body;
} my_t;

union делает так, что cтруктура body и массив raw размещаются в одном и том же куске памяти.
поэтому my_t.body.head будет совпадать с my_t.raw[0],
а my_t.body.bodyA будет совпадать с my_t.raw[1]

Но так просто только пока у Вас типы uint8_t, потому что компилятор вообще-то не гарантирует размещение полей структуры разного размера строго друг за другом.
В общем случае придётся прибегнуть к упакованным структурам (#pragma pack(1) для IAR).

Если компилятор понимает анонимные структуры, то можно сделать проще.


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
megajohn
сообщение Feb 16 2015, 07:32
Сообщение #7


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

Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143



Цитата(AndryG @ Feb 15 2015, 22:11) *
У меня есть массив данных. Одна функция работает со всем массивом data[].
Второй функции интересны в этом массиве только некоторые участки (первый, пятый, девятый-десятый байты, для примера)
Третья должна видеть этот массив сосвсем иначе...


дык зачем огород городить с этим Union ?
так и пишите

uint8_t raw[] = "\x01\x02\x03\x04";

typedef struct{
uint8_t head;
uint8_t dummy[3];
}Sdata_view_1;

typedef struct{
uint8_t dummy[2];
uint8_t body;
}Sdata_view_2;

func1( (Sdata_view_1*)raw );
func2( (Sdata_view_2*)raw );

bool func1( (Sdata_view_1* data )
{
return ( data-> head == 1);
}

bool func2( (Sdata_view_2* data )
{
return ( data->body == 'a' );
}




--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 16 2015, 07:57
Сообщение #8


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(megajohn @ Feb 16 2015, 09:32) *
дык зачем огород городить с этим Union ?
Чтобы возложить на компилятор заботу о выравнивании и контроль типов.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
scifi
сообщение Feb 16 2015, 08:23
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(AndryG @ Feb 15 2015, 22:11) *
У меня есть массив данных. Одна функция работает со всем массивом data[].
Второй функции интересны в этом массиве только некоторые участки (первый, пятый, девятый-десятый байты, для примера)
Третья должна видеть этот массив сосвсем иначе...

Странные желания. Впрочем, пока не описана суть задачи, трудно судить. Может быть, расскажете, зачем всё это? Тогда можно будет предложить что-нибудь из того, что есть в языке Си.
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Feb 16 2015, 09:26
Сообщение #10


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(AndryG @ Feb 15 2015, 22:11) *
...Раз звучат только уточняющие вопросы, значит я слишком много хочу...


Вы не то что много хотите. Вы пытаетесь подходить к решению задачи примитивными азм способами. Но, как тут уже прозвучало - велика вероятность, что Вы не зная сильные стороны языка Си
пытаетесь его заюзать для привыкшего вашего глаза комбинациям.

Любые комбинации выравнивания и обращения к тому или иному элементу массива можно всегда реализовать через структуру+юнион+выравнивание.
Про всё это уже прозвучало выше. Так, что я не ошибусь если озвучу общее впечатление от этого топика:
либо стёб, либо попытка забить микроскопом шуруп.

Озвучивайте задачу и я больше чем уверен, первым-вторым комментом Вас направят в нужное русло. Если не более элегантным способом, то точно рабочим и в стиле Си.
Go to the top of the page
 
+Quote Post
AndryG
сообщение Feb 16 2015, 10:32
Сообщение #11


Частый гость
**

Группа: Свой
Сообщений: 139
Регистрация: 23-05-05
Из: UA
Пользователь №: 5 317



megajohn, вот и я кроме как вставлять "распорки" dummy ничего другого не придумал.

kolobok0, вот полная история.
modbus-slave
В обработке приема, подсчете CRC я работаю с буфером, как с массивом.
В с-функции обработки modbus-функции 3 этот массив должен выглядеть двояко:
(я знаю, что можно записать в rsp и затереть данные в rqs - память экономим)

Код
typedef struct{ // request
  const uint8_t addr;
  const uint8_t func;
  const mbReg16_t first;
  const mbReg16_t count;
} mbFunc3Rqs_t;

typedef struct{ // response
  const uint8_t addr;
  const uint8_t func;
  const uint8_t size;
  mbReg16_t reg[(MB_FRAME_MAX - 6) / 2];
}mbFunc3Rsp_t;

#pragma inline
mbError_t mbFunc3Handler(void *frame){
  mbFunc3Rqs_t *rqs  = frame;
  mbFunc3Rsp_t *rsp  = frame;
  return MBE_NONE;
}


Вместо этого хочу сделать одно мега-union с только необходимыми полями. Избавится от постоянных преобразований типов и плясок с указателями.
Код
union{
  uint8_t raw[MB_FRAME_MAX];
  struct{
    const mbReg16_t first;
    const mbReg16_t count;
  }f3rqs;
  struct{
    mbReg16_t reg[(MB_FRAME_MAX - 6) / 2];
  } f3rsp;
}


Я уже понял, что моя хотелка не из С.
Не зря MISRA ругнулась на union c структурами, а затем обматерила за приведение типов через указатели.
Go to the top of the page
 
+Quote Post
scifi
сообщение Feb 16 2015, 10:39
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(AndryG @ Feb 16 2015, 13:32) *
Вместо этого хочу сделать одно мега-union с только необходимыми полями. Избавится от постоянных преобразований типов и плясок с указателями.

Ну да, и заменить на пляски со структурами и объединениями. Шило на мыло.

Цитата(AndryG @ Feb 16 2015, 13:32) *
Не зря MISRA ругнулась на union c структурами, а затем обматерила за приведение типов через указатели.

Мой вам совет: выкиньте эту мисру куда подальше. Нет, конечно, если нет знания языка Си, то, наверное, полезно, когда над плечом стоит строгий дядька (тётька?) мисра и ругается. Но лучше всё-таки выучить язык Си.
Кстати, на что именно мисра ругается? На структуры в объединении - не верю. На анонимные структуры - охотно верю.
Go to the top of the page
 
+Quote Post
AndryG
сообщение Feb 16 2015, 10:55
Сообщение #13


Частый гость
**

Группа: Свой
Сообщений: 139
Регистрация: 23-05-05
Из: UA
Пользователь №: 5 317



scifi, да я ради интереса включил MISRA посмотреть, насколько далёк мой код от автомобильных стандартов sm.gif
Посты в теме и вдумчивое перечитывание глав кернигана объяснило некоторые её заумные требования.

На какое именно union ругалось уже не помню. Код сто раз перекраивался.

Цитата
Шило на мыло.

Вот я и ищу вариант, как в функции-обработчики отдать необходимый минимум информации, но в то же время без лишних трат памяти.

Go to the top of the page
 
+Quote Post
scifi
сообщение Feb 16 2015, 11:17
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(AndryG @ Feb 16 2015, 13:55) *
Вот я и ищу вариант, как в функции-обработчики отдать необходимый минимум информации, но в то же время без лишних трат памяти.

Не нужно это. Всё-таки язык Си без некоторой дисциплины - это граната в руках обезьяны. Поэтому не нужно пытаться везде подключать статические проверки компилятора. Часто это просто не стоит того, как и в данном случае.
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Feb 17 2015, 21:46
Сообщение #15


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(AndryG @ Feb 16 2015, 13:32) *
...Я уже понял, что моя хотелка не из С. ...


по разному обращаться к одному и тому-же участку памяти - это нормально. Если читаете Кернигана & Ритчи (K&R), то Вы можете придерживаться именно
материала там изложенного, тут всё правильно делаете. Если компилятор не пропускает - то проверяйте всякие глобал настройки среды, должно помочь. Ну и читать мануалы на саму среду разработки.
Т.е. K&R можно воспринимать как отличное описание стандарта сей.

Только не забудьте выравнивание на байт сделать до структур. И ышо выше - сохранить выравнивание, а ниже - восстановить его обратно.

И пару слов про модбас.
Различные девайсы по разному трактуют модбас. Бывало, что даже очерёдность CRC на приёме одна (правильная согласно протоколу), а вот передача левая - перевёрнутая. Так, что танцы
с байтами - один чёрт придётся в рукопашную, согласно настройкам или заточка на конкретику. Так-же встречается не стандартная скорость обмена.
Ну и на последок можно упомянуть об важной замороте в данном протоколе - тайм ауты. ОБЯЗАТЕЛЬНО до передачи и после передачи. Тем самым увеличивая помехозащищённость канала.
Разработчики обычно страдают выключением сразу передатчика, после прерывания освобождения сдвигового регистра после передачи. А в начале передачи даже и не заморачиваются с тайм-аутом.
Это зло на длинных линиях в пром. зоне...

Если не поборете - то напишите ошибку сразу, что есть и чего хочется.
Go to the top of the page
 
+Quote Post

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

 


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


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