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

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

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

Так вот я и выясняю, не может ли она после этого разъехаться ещё больше:)

Представьте, что есть ключ компилятора, который каждый байт в структуре выравнивает на границу слова. С таким ключом всё наше растягивание пойдёт насмарку.

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


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

Так вот я и выясняю, не может ли она после этого разъехаться ещё больше:)

Представьте, что есть ключ компилятора, который каждый байт в структуре выравнивает на границу слова. С таким ключом всё наше растягивание пойдёт насмарку.

Самое простое - не морочить, а заложить где-то assert, только вот что лучше проверять: небось, sizeof какой-то тестовой структуры, не обязательно прям-таки осмысленной и привязанной к реальным портам, но с использованием всех индуистских _IO32 и прочая.

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


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

К счастью, в железе STM32 адреса устройств уже распределены так, что "упаковываются" в структурах согласно своему естественному размеру, int16_t по границам полуслова, int32_t по границам слова. Во всяком случае, я не заметил, чтобы где-то в stm32fxx.h было не так. Поэтому, если не насиловать компилятор прагмами pack(n), ничто расползаться не должно.

А __packed может только утоптать структуру, но не раздвинуть ее. А от этого мы уже защитились RESERVED.

Так, вроде?

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


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

К счастью, в железе STM32 [...]

В принципе, тут зацепились мы за платформенно-независимый вопрос.

Поэтому, если не насиловать компилятор прагмами pack(n)

... а также приведением типов указателей на элемент структуры :) ...

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


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

Допустим, имеется структура из байтов. Хочу инициализировать сразу 2 байта 16-битовым числом, или сразу 4 байта 32-битовым числом. Привожу указатель к нужному типу

Похоже, при формировании структуры си-компилятор находит элемент с максимальной длиной и выделяет каждому элементу структуры размер памяти, равный максимальной длине. По крайней мере, для кейловского компилятора я это доказал. Выделил структуру

typedef struct

{

unsigned long VARA;

unsigned char VARB;

unsigned int VARC;

}

CRCSTRUCT;

 

CRCSTRUCT STRD;

 

и в дибаггере стал туда писать побайтно, начиная с VARА. В VARА записалось 4 байта, как и ожидалось, в VARВ записался один байт, остальные три писались в никуда и не отображались, в VARC записалось два байта, остальные записались в никуда.

 

Так что дырки в структурах всегда будут, если структура содержит элементы разной длины.

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


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

:yeah:

Есть Грабля!

typedef struct
{
char		id[2];
uint32_t	size;
char		reserved[4];
uint32_t	offset;
uint32_t	bmp_infolen;
uint32_t	width;
uint32_t	height;
uint16_t	planes;//number of
uint16_t	bits_per_pix;
uint32_t	compress_type;
uint32_t	picture_size;
uint32_t	Hresolution;
uint32_t	Vresolution;
uint32_t	used_colors;
uint32_t	important_colors;
} bmp_header_t;

Компилим

gcc версия 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

с дефолтными настройками code::blocks (уверяю, там ничего страшного нету, выравнивание нигде принудительно не включено)

Пишет после bmp_header.id два нулевых байта, также при выводе его размера показывает 56 байт супротив 54-х.

В общем, подарок для АНТОХИ. :)

ЗЫ причем, сгенеренный и исходный BMP отличаются ровно на этих 2 байта

PPS добавили #pragma pack(1) - получили всё, что надо. 54 байта.

Оттакот!

ppps Что-то пользоваться таким ГЦЦ расхотелось...

Изменено пользователем _Pasha

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


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

typedef struct
{
    char        id[2];
    uint32_t    size;

И что же вы ожидали (надеюсь, это был не AVR или MSP430)?

 

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


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

:yeah:

Есть Грабля!

Да вроде не особо, uint32_t выровняли на 4 байта. Не вижу криминала:)

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


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

Да вроде не особо, uint32_t выровняли на 4 байта. Не вижу криминала:)

Разобрался... чего-то вбил себе в голову, что uint16_t там не подряд идут. И непонятно, чего там так, там эдак. Тогда всё правильно.

Изменено пользователем _Pasha

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


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

Всплыл вопрос, кажется, подойдет в эту тему.

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

 

Теперь хочу копировать суперструктуру в другую, такую же (backup). Хочу делать это 32-битовыми пересылками. Кроме того, хочу вычислять аппаратно CRC суперструктуры, туда тоже нужно посылать 32-битовые слова.

Задаю указателю на uint32 адрес суперструктуры (uint32_t *)&Ctrl. Вычисляю ее размер в словах (!) size(Ctrl_t) / 4. И так собираюсь использовать.

 

Вопросы:

1. Что гарантирует, что вся суперструктура разместится по выровненному до слова адресу? Что будет, если первый элемент - 8-битовый?

2. Как задать, чтобы ее размер был равен целому числу слов? Пока напихал несколько пустых байтов, каждая мелкая структура - по 2-4-8 байтов, общее количество 44 байта (но, может, есть и дыры двухбайтовые?). В конце суперструктуры задаю 32-битовую CRC, это гарантирует выравнивание по словам, и целое число слов?

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


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

1. Что гарантирует, что вся суперструктура разместится по выровненному до слова адресу? Что будет, если первый элемент - 8-битовый?

Если явно определено выравнивание (pack или aligned), то вроде как должно.

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


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

Почитал здесь - http://www.keil.com/support/man/docs/armcc...he.htm#Cihbbgii

Похоже, ничего делать не надо.

 

Если явно определено выравнивание (pack или aligned), то вроде как должно.

Похоже, лучше, наоборот, ничего не задавать. Тогда само разместится ровненько.

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


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

2. Как задать, чтобы ее размер был равен целому числу слов?

 

Я точно не вспомню, но делал что то типа такого:

Помещал "супер структуру" + массив байт в "супер-супер структуру"

Размерность массива байт задавал как остаток от деления sizeof("супер структура") на 4.

Единственное, что не могу вспомнить, как обходил ситуацию с нулевым размером массива байт.

 

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


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

Запустил компиляцию с опцией --remarks.

Вижу:

enum занимают по 32 бита! Неоправданная роскошь.

К структуре с enum и 3-мя uint_16 добавилось... видимо 2 байта в конце.

По структуре Ctrl никаких замечаний не увидел.

 

Добавил uint8_t в конец Ctrl. Получил замечание, что добавило padding.

Делаю вывод - ничего не бойся, не проси... :rolleyes: Сам Кейл придет и принесет.

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


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

enum занимают по 32 бита! Неоправданная роскошь.

Каждый из элементов enum - это int. Так что если машинное слово 32-х разрядное, то всё верно.

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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