Битовые поля сделаны более оптимизированными - PullRequest
0 голосов
/ 04 июля 2019

Я делаю код для 16-битного микропроцессора. Моя память довольно ограничена в 128 КБ. Компилятор IAR C / C ++ для MSP430 Мне нужно реализовать код для экономии памяти.

Я пытался реализовать это с помощью этой реализации характеристики C.

struct {
    unsigned int widthValidated : 1;
    unsigned int heightValidated : 1;
} status;

Но с этим битом кода я все еще использую только 1 бит 16-битного слова.

Моя цель - использовать бит памяти одного размера для двух 8-битных переменных. Первая переменная должна быть на 8 бит слева от второй переменной.

struct {
   unsigned int widthValidated : 8; //8 bits for this
   unsigned int heightValidated : 8; // 8 left over for this
} status;

Возможно ли это? Есть ли реализации этого или есть библиотека в C для этого? Как мне это сделать?

Ответы [ 3 ]

1 голос
/ 04 июля 2019

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

Что вам следует сделать, это использовать типы stdint.h.Объявите две uint8_t переменные.Вы экономите память в микроконтроллерах, тщательно выбирая необходимый тип при объявлении переменной.

Например, в профессиональных программах для ограниченных микроконтроллеров типичный цикл for записывается как for(uint8_t i=0; ..., а не как «небрежный ввод» for(int i=0; ....

Хитрость в том, что всякий раз, когда вы объявляете любую переменную, тогда всегда учитывает, какое максимальное значение может получить эта переменная.Тем самым вы экономите память и предотвращаете ошибки переполнения.

0 голосов
/ 04 июля 2019

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

Вот как я понимаю, вы хотите, чтобы размер вашей памяти составлял два байта в одном 16-битном слове.

struct {
    uint8_t widthValidated;
    uint8_t heightValidated;
} status;

Требовать от компилятора создания определенной границы вы можете сделать:

для arm:

struct __attribute__((packed)){
    uint8_t widthValidated;
    uint8_t heightValidated;
} status;

для gcc:

#pragma pack (1)
struct __attribute__((packed)){
    uint8_t widthValidated;
    uint8_t heightValidated;
} status;

Ваша платформа может отличаться, но она должна найти способ сделать это, когда вы ищете структуру упаковки.

Объединение внутри структуры также может быть вариантом, но это не обязательно будет переносимым как бит / байтпорядок заказа может отличаться от платформы к платформе.

Вы видите меня, используя uint8_t выше.Это typedef сделано внутри <stdint.h>.Это стандартизированный способ объявления целочисленной переменной определенной ширины.Полезные типы внутри микроконтроллера: неопределенное целочисленное семейство: uint8_t (8-бит), uint16_t (16-бит) и uint32_t (32-бит).И их подписанные аналоги: int8_t (8-бит), int16_t (16-бит) и int32_t (32-бит).

0 голосов
/ 04 июля 2019

Если вы хотите сохранить память, просто используйте меньшие типы, когда вы объявляете структуру

typedef struct
{
    uint8_t flag1: 1;
    uint8_t flag2: 1;
    uint8_t flag3: 1;
    uint8_t flag4: 1;
    uint8_t flag5: 1;
}myflags;

uint8_t foo(myflags f)
{
    return f.flag4;
}

uint8_t foo1(uint8_t flags)
{
    return !!(flags & (1 << 3));
}

void foo3()
{
    printf("%zu\n", sizeof(myflags));
}

, это облегчает чтение и отладку кода и его модификацию.

foo:
        ubfx    r0, r0, #3, #1
        bx      lr
foo1:
        ubfx    r0, r0, #3, #1
        bx      lr
foo3:
        movs    r1, #1
        ldr     r0, .L5
        b       printf
.L5:
        .word   .LC0
.LC0:
        .ascii  "%zu\012\000"

Многие СК имеют специальныеинструкции по извлечению битовых полей перемещают их в младшие биты, а подписанные и без знака расширяют результат до размера регистра / переменной

...