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

Приведение типа указателя на элемент структуры

Я не знаю, что надо сделать, но точно знаю теперь, чего не надо..

Не надо использовать такие структуры без принудительной упаковки, во избежание.

Мне совершенно было не смешно, когда port1.out.pin3 = 1 махал битами в регистре dir вместо out (а это ещё надо было найти)

Скорее всего был локальный глюк какой-то конкретной версии mspgcc. Хотя принудительная упаковка - дело несложное, можно и её добавить, для пущей уверенности.

 

Вставить #pragma pack(n) или указать транслятору -fpack-struct=n cо значением n отличным от 1.

К сожалению, в документации на gcc нигде нет упоминания: какое значение n (величина выравнивания) принято "по-умолчанию"...

Нет, ничего из этого не увеличивает размер структуры. Проверил и с #pragma pack(x), и с -fpack-struct=x (x={4,8,16,32}), и с ними обоими одновременно.

До кучи проверил __attribute__ ((packed)) и __attribute__ ((aligned (x))) для типа.

Размер структуры равен 2, как я не извращался :)

Единственный вариант, который изменил размер, был вот такой:

typedef struct
{
    unsigned char a __attribute__ ((aligned (8)));
    unsigned char b __attribute__ ((aligned (8)));
}str;

Но этот вариант не страшен, потому что явно указывать alignment там, где он не нужен, мы не будем.

 

Дык я это "не то не к тому" унаследовал, пытаясь сказать, что сабжевое приведение - лишняя суета и потенциальный источник проблем.

А, вон оно что! Теперь понял:)

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


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

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

Приведение типов - не хак. А осознанная необходимость. Я не с дырами борюсь, их у меня нет. А хочу писать не только 8-битовыми словами, но и 16-битовыми, 32-битовыми. Cortex-M это позволяет делать, начиная с любого адреса. Тем более, регистры микроконтроллера (или контроллера ЖКИ, который использую) и так выровнены по адресам.

Приведение типов указателя - обычное дело.

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


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

Нет, ничего из этого не увеличивает размер структуры.
А теперь попробуйте проверить на такой структуре:

typedef struct
{
    unsigned char a;
    unsigned int  b;
    unsigned char c;
}str;

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


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

Вообще то компиляторы упаковывают структуры не от их [компилятора] большого желания, а от требования выполнить ограничения по выравниванию для полей этих самых структур. Так что, если у вас в структуре нет полей с требованиями по выравниванию (например у вас там все char) - то ничего выравниваться и не будет. А вот если есть - то перед этим полем может появится дыра, и вся структура в целом получит ограничение по выравниванию, как для этого поля (что в свою очередь может добавить дыру и в конце структуры)

Например (предполагаю требования по выравниванию на размер поля):

struct {
int8_t f8;
int16_t f16;
int32_t f32;
int8_t  f8_2;
};
// Превратится в 
struct {
int8_t f8;
int   :8; // Выравнивание для f16 на границу 2х байтов
int16_t f16;
int  :16; // Выравнивание для f32 на границу 4х байтов
int32_t f32;
int8_t f8_2;
int :24; // Выравнивание размера всей структуры, как требует поле f32
};

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


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

int :16; // Выравнивание для f32 на границу 4х байтов

лишнее

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


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

Приведение типов - не хак. А осознанная необходимость.

***

Cortex-M это позволяет делать, начиная с любого адреса.

:biggrin: А сколько воплей у народа по поводу невыровненного доступа на AT91** например! Там не особо позволяет 7tdmi.

 

лишнее

Оно уже для другого: читаем программу и если чего-то надо добавить, сразу видим, сколько бит осталось.

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


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

А теперь попробуйте проверить на такой структуре:

Да, но речь шла о структурах, уже имеющих вручную сформированные отступы, типа такой:

typedef struct
{
    uint8_t a;
    uint8_t padder1;    // - отступ
    uint16_t b;
    uint16_t padder2;  // - отступ
    uint32_t c;
}str;

Такие структуры используются, в частности, в заголовочных файлах от ST для описания периферии процессоров STM32. И меня интересует вопрос, могут ли такие структуры при каких-либо условиях перестать соответствовать описываемой ими периферии.

Пока получается, что всё нормально, соответствуют при любых ключах компиляции. (Ну, кроме непонятного случая, описанного MrYuran-ом)

 

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


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

Вставить #pragma pack(n) или указать транслятору -fpack-struct=n cо значением n отличным от 1.

 

Раз тут пошли "страшные истории"...

pragma pack(n) надо обязательно закрывать pragma pack()

При включении заголовка с незакрытой прагмой такие интересные косяки проявляются - все структуры в одном модуле сами собой "упаковываются", а в другом - остаются неупакованными, в зависимости от последовательности #include.

 

Пример для наглядности:

a.h: 
#pragma pack (1)

b.h
typedef struct .... b_struct;

a.c
#include "a.h"
#include "b.h"
b_struct A;

b.h
#include "b.h"
b_struct B;

 

Так вот, A и B получились РАЗНЫЕ, хотя этого вряд-ли кто-то добивался :-)

Короче, плохая это прагма, не ленитесь писать атрибуты для каждой структуры.

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


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

Пока получается, что всё нормально, соответствуют при любых ключах компиляции. (Ну, кроме непонятного случая, описанного MrYuran-ом)
Там, я так понял, ещё битовые поля были в подструктурах ioregister_t.

Что-то могло и на этом набежать.

Скажем,

typedef {
    unsigned f : 1;
} flag_t;

typedef {
    flag_t a;
    flag_t b;
} flags2_t;

структура flags2_t займёт 2*sizeof(unsigned), а не один байт. Причём никакие pack не помогут.

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


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

Короче, плохая это прагма, не ленитесь писать атрибуты для каждой структуры

а если есть некая структура

typedef struct{
  u8 b;
  u32 c;  
  u8 d;
  u16 a;  
} t_struct_A;

 

и указатель

t_struct_A * p;

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

u8 buff[100500];
p = &buff[17];

в каком именно месте и какие прагмы должны стоять чтобы p->c = 0xABCD1234; нормально работало всегда и везде?

или так лучше вообще не делать, а данные просто макросами по байтам по смещениям вытаскивать чтобы ни от платформы ни от компилятора не зависеть?

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


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

Там, я так понял, ещё битовые поля были в подструктурах ioregister_t.

Что-то могло и на этом набежать.

Наверное.

Ну а в результате, какой будет вывод? Можно безбоязненно пользоваться структурами от ST? Или ждать, когда _Pasha сделает базу данных? :)

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


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

Можно безбоязненно пользоваться структурами от ST?

Если программируем аппаратные средства микроконтроллеров STM32xxx, то используются не структуры, а указатели на типы структур, расположенные по фиксированным адресам.

Если просто пользуемся структурами, подобными предложенным ST, то не все ли равно, как упакованы данные? Куда записали, оттуда и прочитаем.

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


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

Если программируем аппаратные средства микроконтроллеров STM32xxx, то используются не структуры, а указатели на типы структур, расположенные по фиксированным адресам.

Какая нафиг разница? Если структура вдруг разъедется, то мы промахнёмся мимо нужного регистра и по указателю:)

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


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

Какая нафиг разница? Если структура вдруг разъедется, то мы промахнёмся мимо нужного регистра и по указателю:)

Как же она разъедется, если указателю передан конкретный адрес! А дыры зарезервированы неиспользуемыми переменными.

P.S. Мы же ее (структуру) уже разъехали разъездили раскатали растянули.

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


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

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

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

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

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

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

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

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

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

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