|
|
  |
Ньюансы IAR-а, Alignment |
|
|
|
Dec 8 2010, 09:49
|
Частый гость
 
Группа: Участник
Сообщений: 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
|
|
|
|
|
Dec 8 2010, 10:18
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 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 =)
|
|
|
|
|
Dec 8 2010, 10:20
|
Знающий
   
Группа: 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
|
|
|
|
|
Dec 8 2010, 10:25
|

Гуру
     
Группа: Свой
Сообщений: 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 байт - наверное, из-за выравнивания)
|
|
|
|
|
Dec 8 2010, 10:28
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
Цитата Да но я же ее не выравнивал CPU 16 битное по этому все структуры по умолчанию выравниваются к 16 битам, если поставите #pragma pack(1) получите размер 7 байт, если поставите #pragma pack(2), будет такойде размер, так как компилятор выравнивает к такому значению по умолчанию.
|
|
|
|
|
Dec 8 2010, 10:34
|
Частый гость
 
Группа: Участник
Сообщений: 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), будет такойде размер, так как компилятор выравнивает к такому значению по умолчанию. Спасибо понял.
|
|
|
|
|
Oct 26 2011, 08:03
|
Частый гость
 
Группа: Участник
Сообщений: 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
|
|
|
|
|
Oct 26 2011, 09:14
|
Гуру
     
Группа: Свой
Сообщений: 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 бит он прочитать может с любого места.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Oct 26 2011, 11:18
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Oct 28 2011, 20:44
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|