Перейти к содержанию
    

iar struct union как указать смещение?

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

 

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

 

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...Понятно, что всё работает неверно....

 

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

 

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

 

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

 

ЗЫ

Надеюсь аспекты выравнивания данных Вами изучены и в дальнейшем на азы языка мы не свалимся?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Каким полям?

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

Объединения (union) для того и придуманы, а иначе они превратятся в структуры.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

ссылка

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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 с превращением объединения в структуру это вы верно подметили :)

 

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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).

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня есть массив данных. Одна функция работает со всем массивом 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' );

}

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

дык зачем огород городить с этим Union ?
Чтобы возложить на компилятор заботу о выравнивании и контроль типов.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня есть массив данных. Одна функция работает со всем массивом data[].

Второй функции интересны в этом массиве только некоторые участки (первый, пятый, девятый-десятый байты, для примера)

Третья должна видеть этот массив сосвсем иначе...

Странные желания. Впрочем, пока не описана суть задачи, трудно судить. Может быть, расскажете, зачем всё это? Тогда можно будет предложить что-нибудь из того, что есть в языке Си.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

пытаетесь его заюзать для привыкшего вашего глаза комбинациям.

 

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

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

либо стёб, либо попытка забить микроскопом шуруп.

 

Озвучивайте задачу и я больше чем уверен, первым-вторым комментом Вас направят в нужное русло. Если не более элегантным способом, то точно рабочим и в стиле Си.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 структурами, а затем обматерила за приведение типов через указатели.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вместо этого хочу сделать одно мега-union с только необходимыми полями. Избавится от постоянных преобразований типов и плясок с указателями.

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

 

Не зря MISRA ругнулась на union c структурами, а затем обматерила за приведение типов через указатели.

Мой вам совет: выкиньте эту мисру куда подальше. Нет, конечно, если нет знания языка Си, то, наверное, полезно, когда над плечом стоит строгий дядька (тётька?) мисра и ругается. Но лучше всё-таки выучить язык Си.

Кстати, на что именно мисра ругается? На структуры в объединении - не верю. На анонимные структуры - охотно верю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

scifi, да я ради интереса включил MISRA посмотреть, насколько далёк мой код от автомобильных стандартов :)

Посты в теме и вдумчивое перечитывание глав кернигана объяснило некоторые её заумные требования.

 

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

 

Шило на мыло.

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...Я уже понял, что моя хотелка не из С. ...

 

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

материала там изложенного, тут всё правильно делаете. Если компилятор не пропускает - то проверяйте всякие глобал настройки среды, должно помочь. Ну и читать мануалы на саму среду разработки.

Т.е. K&R можно воспринимать как отличное описание стандарта сей.

 

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

 

И пару слов про модбас.

Различные девайсы по разному трактуют модбас. Бывало, что даже очерёдность CRC на приёме одна (правильная согласно протоколу), а вот передача левая - перевёрнутая. Так, что танцы

с байтами - один чёрт придётся в рукопашную, согласно настройкам или заточка на конкретику. Так-же встречается не стандартная скорость обмена.

Ну и на последок можно упомянуть об важной замороте в данном протоколе - тайм ауты. ОБЯЗАТЕЛЬНО до передачи и после передачи. Тем самым увеличивая помехозащищённость канала.

Разработчики обычно страдают выключением сразу передатчика, после прерывания освобождения сдвигового регистра после передачи. А в начале передачи даже и не заморачиваются с тайм-аутом.

Это зло на длинных линиях в пром. зоне...

 

Если не поборете - то напишите ошибку сразу, что есть и чего хочется.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...