Организация структур
Для объединения нескольких переменных, относящихся к одной сущности, используют структуры. Может показаться, что расположение полей не имеет особого значения, однако это не так: плотность кода (англ. code density) можно улучшить простым перемешиванием полей, точнее, правильной упорядоченностью. Сравним две структуры:
struct {
char a;
int b;
char c;
short d;
} FIRST;
struct {
char a;
char c;
short d;
int b;
} SECOND;
Замерив размер функцией sizeof()
, мы увидим, что FIRST
занимает 12 байт, а размер SECOND
при том же содержании оказывается меньше — всего 8 байт.
Структура FIRST
в памяти:
1 | 2 | 3 | 4 |
---|---|---|---|
— | — | — | a[7:0] |
b[31:24] | b[23:16] | b[15:8] | b[7:0] |
— | c[7:0] | d[15:8] | d[7:0] |
Структура SECOND
в памяти:
1 | 2 | 3 | 4 |
---|---|---|---|
a[7:0] | c[7:0] | d[15:8] | d[7:0] |
b[31:24] | b[23:16] | b[15:8] | b[7:0] |
Помните, что размер слова — 32 бита, а процессор ARM может эффективно заполнять это пространство, используя специальные инструкции чтения или записи полуслова и байта. Другими словами, сортируйте переменные в структуре в порядке увеличения их размера: сначала 8-битные, затем 16-, 32- и 64-битные переменные, а уже после них массивы. Разрешить проблему можно по-другому, добавив атрибут __attribute__((packed))
перед названием типа (любой структуры).
// ...
} __attribute__((packed)) FIRST;
// sizeof(FIRST) == 8
Иногда, напротив, нужно быть уверенным, что структура занимает четное количество полуслов/слов в памяти. В таком случае нужно добавить aligned(x)
, где x
— степень двойки.
typedef enum {
uint8_t name[10];
} __attribute__((packed, aligned(2))) SETTINGS_t;
// sizeof(SETTINGS_t) == 10
typedef enum {
uint8_t name[10];
} __attribute__((packed, aligned(4))) SETTINGS_t;
// sizeof(SETTINGS_t) == 12
>Вопрос 48. Какой тип целочисленной переменной лучше всего СПОЛЬЗОВАТЬ в микроконтроллере PIC24 и почему?
Здравствуйте.
Мучаю STM32F030F4P6 и изучаю вашу книгу.
Замерял сегодня скорость выполнения вышеприведённых циклов на разных оптимизациях кода O1 O2 O3.
И у меня получилось что цикл
for (i = 0; i < 1000000; i++) {} выполняется на любой оптимизации за 4800 микросекунд
цикл for ( i = 1000000; i != 0; i—){} выполняется за 4800 микросек. только на оптимизации O1 . При оптимизации O2 и O3 он выполняется за 10800 микросекунд.
цикл
n = 1000000;
do {
// code here
} while (—n != 0); на любой оптимизации выполняется за 10800 микросекунд
может это связано с компиляцией и оптимизацией именно для данного чипа.
но лучше я буду писать for (i = 0; i < 1000000; i++){}
Взял осциллограф и всё перепроверил. Оказалось что у меня таймер переполнялся.
Думаю что мои коменты публиковать не нужно )