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

 
 
 
Reply to this topicStart new topic
> Ньюансы IAR-а, Alignment
Twen
сообщение Dec 8 2010, 09:49
Сообщение #1


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

Группа: Участник
Сообщений: 163
Регистрация: 7-02-09
Пользователь №: 44 543



Здравствуйте. Есть директива #pragma pack(), упаковка структуры не совсем понятен параметр функции pack (1,2,4,8 или 16)...а IAR(msp) записует переменные в память ОЗУ по чётным адресам так как указатель двухбайтовый (это связано с архитектурой msp)? На сколько я понимаю из-за этого и нужно применять выравнивание ? И объясните пожалуйста использование директивы #pragma data_alignment=(1,2,4...)...вообще непонятно всё, что связано с alignment...
Заранее спасибо )


Также есть вопрос по поводу битового поля.
struct fff {
unsigned char first : 1; //1 -количество бит в поле
unsigned char second : 1;
unsigned char third : 1;
unsigned char forth : 1;
unsigned char fifth : 1;
unsigned char sixth : 1;
unsigned char sevnth : 1;
unsigned char eighth : 1;
};
a=sizeof(struct fff); //a=1;

а если изменить на int 2 бита

struct fff {
unsigned char first : 1; //1 -количество бит в поле
unsigned char second : 1;
unsigned int third : 1;
unsigned char forth : 1;
unsigned char fifth : 1;
unsigned int sixth : 1;
unsigned char sevnth : 1;
unsigned char eighth : 1;
} ;
то

a=sizeof(struct fff); //a=10;


Не понятно, почему размер структуры стал 10 байт???

Заранее спасибо )


Сообщение отредактировал Twen - Dec 8 2010, 09:40
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Dec 8 2010, 10:18
Сообщение #2


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(Twen @ Dec 8 2010, 12:49) *
Не понятно, почему размер структуры стал 10 байт???

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

.. а нечего извращаться.

Выравнивание и упаковка - вещи параллельные.
Выравнивание - каждая переменная начинается с адресов определённой кратности (1,2,...)
Упаковка - это заполнение пустот в структуре, образующихся засчёт перемешивания типов разной длины.
Например, без упаковки char char int займут 6 байт, а в упакованной структуре два char-a объединятся в одно 16р слово и структура будет 4 байта длиной.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Dec 8 2010, 10:20
Сообщение #3


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



IAR тут не причем, учите С


Цитата
Не понятно, почему размер структуры стал 10 байт???


Вот так будет лежать ваша структура в памяти

first и second ляжут в 1 байт, потом будет ити pad, так как следующая переменная int котороя требует ваыравнивания отсюда и pad,
third - зеймет 2 байта далее forth и fifth которые тоже ляжут в 1 байт, но заними опять int перед которым будет pad.
sixth - зеймет 2 байта за ним sevnth и eighth.

Считаем: 1+PAD+2+1+PAD+2+1+PAD = 10

Цитата
И объясните пожалуйста использование директивы #pragma data_alignment=(1,2,4...)


Это расписано IAR C/C++ Development Guide, у паковка структур фича не только IAR


Go to the top of the page
 
+Quote Post
Twen
сообщение Dec 8 2010, 10:23
Сообщение #4


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

Группа: Участник
Сообщений: 163
Регистрация: 7-02-09
Пользователь №: 44 543



Да но я же ее не выравнивал, почему она выровнялась по четным адресам и, что значит разбилась на 5?
unsigned char first : 1; //- поле 1, 1 бит
unsigned char second : 1; //поле 2, 1бит
unsigned int third : 1; // поле 3, 1 бит...
unsigned char forth : 1;
unsigned char fifth : 1;
unsigned int sixth : 1; // поле 6, 1 бит...
unsigned char sevnth : 1;
unsigned char eighth : 1;// поле 7, 1 бит...
Go to the top of the page
 
+Quote Post
Палыч
сообщение Dec 8 2010, 10:25
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Twen @ Dec 8 2010, 12:49) *
Не понятно, почему размер структуры стал 10 байт???
У меня получилось 7 байт (правда, для AVR), что вполне объяснимо. В стандарте допускается int или unsigned int. IAR разрешает и другие типы (например, unsigned char). Но, при смешении типов получаем (Ваш пример):
first, second - по биту в unsigned char
third - один бит в unsigned int
forth, fifth - по биту в unsigned char
sixth - один бит в unsigned int
sevnth, eighth - по биту в unsigned char
Итого = 7 байт (Ваши 10 байт - наверное, из-за выравнивания)
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Dec 8 2010, 10:27
Сообщение #6


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(Палыч @ Dec 8 2010, 13:25) *
Итого = 7 байт (Ваши 10 байт - наверное, из-за выравнивания)

Если упаковать, будет 7


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Dec 8 2010, 10:28
Сообщение #7


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



Цитата
Да но я же ее не выравнивал


CPU 16 битное по этому все структуры по умолчанию выравниваются к 16 битам, если поставите #pragma pack(1) получите размер 7 байт, если поставите #pragma pack(2), будет такойде размер, так как компилятор выравнивает к такому значению по умолчанию.


Go to the top of the page
 
+Quote Post
Twen
сообщение Dec 8 2010, 10:34
Сообщение #8


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

Группа: Участник
Сообщений: 163
Регистрация: 7-02-09
Пользователь №: 44 543



Цитата
Вот так будет лежать ваша структура в памяти

first и second ляжут в 1 байт, потом будет ити pad, так как следующая переменная int котороя требует ваыравнивания отсюда и pad,
third - зеймет 2 байта далее forth и fifth которые тоже ляжут в 1 байт, но заними опять int перед которым будет pad.
sixth - зеймет 2 байта за ним sevnth и eighth.

Считаем: 1+PAD+2+1+PAD+2+1+PAD = 10


Спасибо MALLOY2, понял!

Ну так а почему выравнивание почётным адресам происходит?

Цитата
CPU 16 битное по этому все структуры по умолчанию выравниваются к 16 битам, если поставите #pragma pack(1) получите размер 7 байт, если поставите #pragma pack(2), будет такойде размер, так как компилятор выравнивает к такому значению по умолчанию.


Спасибо понял.
Go to the top of the page
 
+Quote Post
Twen
сообщение Oct 26 2011, 08:03
Сообщение #9


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

Группа: Участник
Сообщений: 163
Регистрация: 7-02-09
Пользователь №: 44 543



Добрый день. Опять возвращаюсь к этой теме, мне не дает покоя непонимание некоторых вещей, так как знакомых опытных программистов у меня нет, пишу опять сюда.
На сколько я понимаю, размер типа int зависит от архитектуры процессора, для 32 разрядных это 32 бита, для 16 - 16 бит. Аналогично от платформы зависят и целые типы short, long. Например для Cortex M3 я проверял в иаре int = 4байта, short = 2, long = 4!(тоже что и int)!!! Возникает вопрос, есть ли еще какие-то плаформо-зависимые типы ?
Второй непонятный момент, как происходит выравнивание я понял, благодаря высшее описанному разговору, но...
Для примера возьмем cortex M3/
1.Есть внутренняя память Flash и ОЗУ, доступ к ней обеспечивается через 32 разрядные шины данных и адресную. Выходит для того, чтобы прочитать байт, процессор должен вычитать 32 разрядную ячейку и отбросить лишнее, а для записи процессор должен : Read 32 (0x 11 22 33 44) ->( (0x 11 22 33 44 & 0xFF FF FF 00) | Byte) -> записать результат. (считать 32 разр. ячейку, сделать логическое "&" а потом "|" c байтом и записать результат)?
Я смотрел аcсемблерные команды для Cortex M3, там есть команды чтения, записи байта, слова...ну они наверное не так реализуются, как я описал, так бы было очень не производительно.

2.Если в памяти по умолчанию производиться выравнивание к адрессу кратному 4, то выходит, что если у нас есть RAM = 1кБт (это 256 32-ух разрядных слов) , при использовании в программе 256 переменных типа char, получилось бы, что память стала полностью заполнена, а реально мы использовали только 1/4 памяти.
Если в командах ядрах есть доспуп к любой ячейки памяти, то зачем тогда выравнивать вообще? Если процессор может понять, что структура была упакована, то почему компилятор сам не пакует так данные размещенные у RAM?

Спасибо.

Сообщение отредактировал Twen - Oct 26 2011, 08:07
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Oct 26 2011, 09:14
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Twen @ Oct 26 2011, 11:03) *
для записи процессор должен : Read 32 (0x 11 22 33 44) ->( (0x 11 22 33 44 & 0xFF FF FF 00) | Byte) -> записать результат. (считать 32 разр. ячейку, сделать логическое "&" а потом "|" c байтом и записать результат)?

Это делается аппаратно, меньше об этом думайте, и все будет хорошо.

Типы переменных, независимые от платформы, находятся они в файле stdint.h.

Да, по поводу выравнивания. Необходимость выравнивания зависит от длины переменной. Контроллер не может прочитать переменную 32 бит с переходом за границу выравнивания. Но переменную 8 бит он прочитать может с любого места.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 26 2011, 11:18
Сообщение #11


Гуру
******

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



QUOTE (Twen @ Oct 26 2011, 11:03) *
Возникает вопрос, есть ли еще какие-то плаформо-зависимые типы ?
char (должен быть не меньше восьми битов, больше - пожалйста. float и double могут быть по 32 бита. Короче - все базовые типы.
QUOTE (Twen @ Oct 26 2011, 11:03) *
Если в командах ядрах есть доспуп к любой ячейки памяти, то зачем тогда выравнивать вообще?
Не во всех архитектурах невыровненый доступ дается бесплатно. Разве что на 8-битках. Но поробуйте организовать такую структуру - и получите те же проблемы на AVR:
CODE
struct test
{
   uint8_t   a:6;
   uint8_t   b:4;
   uint8_t   c:6;
}
Обратитесь к элементу b этой структуры и почувствуете в листинге примерно то же, что многоразрядные процессоры чувствуют при невыровненном доступе.
Кое-где он может занимать больше времени (потому что все "волшебство" спрятано внутри ядра), где-то компилятор будет вынужден считывать каждую невыровненную переменную побайтно и в регистрах из нескольких байтов собирать одно большое число. Ну представьте себе, что у вас память снаружи и соединена 16-битной шиной. И если переменная не ложится ровно на шину данных - то процессору в любом случае придется делать несколько обращений, выбирая разные адресные входы.

QUOTE (Twen @ Oct 26 2011, 11:03) *
Если процессор может понять, что структура была упакована, то почему компилятор сам не пакует так данные размещенные у RAM?

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

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


--------------------
На любой вопрос даю любой ответ
"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
Twen
сообщение Oct 26 2011, 13:09
Сообщение #12


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

Группа: Участник
Сообщений: 163
Регистрация: 7-02-09
Пользователь №: 44 543



На stm32 нормально работает, short - 2 байта(6,4,6); Переменная b находится на границе 2 байт.

typedef struct
{
short a:6;
short b:4;
short c:6;
} test;

Спасибо за объяснения, переменные в зависимости от их типов автоматически выравниваются отладчиком, для uint32_t - это адресс кратен 4, да uint8_t - 1.



Сообщение отредактировал Twen - Oct 26 2011, 13:39
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 28 2011, 20:44
Сообщение #13


Гуру
******

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



QUOTE (Twen @ Oct 26 2011, 16:09) *
На stm32 нормально работает, short - 2 байта(6,4,6); Переменная b находится на границе 2 байт.
Конечно. Вся структура скопом грузится в 32-разрядный регистр. Я предлагал посмотреть на код для 8-разрядного процессора.
QUOTE (Twen @ Oct 26 2011, 16:09) *
переменные в зависимости от их типов автоматически выравниваются отладчиком
Отладчик только показывает. Выравниваются они компилятором, а в остальном - верно.


--------------------
На любой вопрос даю любой ответ
"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

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

 


RSS Текстовая версия Сейчас: 24th June 2025 - 21:07
Рейтинг@Mail.ru


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