8 бит тип enum в C


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

Мне нужно сохранить прозрачность между именем команды и ее значением. Чтобы избежать необходимости перевода 8-битного числа, полученного в последовательном режиме, в любой тип.

Я хотел бы использовать перечисления для работы с ними в моем коде. Только перечисление соответствует на этой платформе 16-битному целому числу.

Платформой является микроконтроллер AVR ATmega169V, на демонстрационная доска Butterfly . Это 8-битная система с некоторой ограниченной поддержкой 16-битных операций. Это не быстрая система и имеет около 1 Кб оперативной памяти. В нем нет никаких предметов роскоши, таких как файловый ввод/вывод или операционная система.

Итак, какие предложения относительно того, какой тип я должен использовать для хранения 8-битных команд?
Должно быть что-то получше, чем массивный заголовок #defines.

6 23

6 ответов:

gcc's -fshort-enums может быть полезно:

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

На самом деле, здесь Страница с большим количеством соответствующей информации. Я надеюсь, что вы столкнетесь со многими коммутаторами GCC, о существовании которых вы и не подозревали. ;)

Вы пытаетесь решить проблему, которой не существует.

Ваш вопрос помечен C. В языке C типы enum в контексте значений полностью совместимы с целочисленными типами и ведут себя так же, как и другие целочисленные типы. При использовании в выражениях они подвергаются точно такому же интегральному продвижению, как и другие интегральные типы. Как только вы это учтете, вы должны понять, что если вы хотите хранить значения, описываемые константами перечисления в 8-битном целочисленном типе, все, что вам нужно do-это выбрать подходящий универсальный 8-битный интегральный тип (скажем int8_t) и использовать его вместо типа enum. Вы ничего не потеряете, если будете хранить значения констант enum в объекте типа int8_t (в отличие от объекта, явно объявленного с типом enum).

Проблема, которую вы описываете, существовала бы в C++, где типы enum отделены гораздо дальше от других интегральных типов. В C++ использование интегрального типа вместо перечислительного типа с целью экономии памяти является более сложным (хотя вероятный). Но не в С,где это не требует никаких дополнительных усилий.

Я не понимаю, почему перечисление не работает. Сравнения с перечислением и назначения из него должны работать нормально с расширением по умолчанию. Просто будьте осторожны, чтобы ваши 8-битные значения были подписаны правильно (я думаю, что вы хотели бы беззнаковое расширение).

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

Компилятор Microsoft C позволяет сделать что-то вроде этого, но это расширение (оно стандартно в C++0x):

enum Foo : unsigned char {
    blah = 0,
    blargh = 1
};

Поскольку вы отметили GCC, я не совсем уверен, возможно ли то же самое, но GCC может иметь расширение в режиме gnu99 или что-то для него. Дайте ему шанс.

Я бы рекомендовал остановиться на перечислении в любом случае по следующим причинам:

  • это решение позволяет вам сопоставлять значения команд непосредственно с тем, что ожидает ваш последовательный протокол.
  • Если вы действительно используете 16-битную архитектуру, то есть не так много преимуществ, чтобы перейти к 8-битному типу. Думать о других аспектах, то 1 байт памяти.
  • в некоторых компиляторах я использовал фактический размер перечисления, использовал минимальное количество битов (перечисления, которые могли бы поместиться в байт, использовали только байт, затем 16 бит, затем 32).

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

В качестве последней опции вы можете определить 'enum' как данные представления для команд и использовать преобразование в байт с помощью 2 простых операций для хранения / восстановления значения команды в / из памяти (и инкапсулировать это в одном месте). А как насчет этого? Это очень важно. простые операции, так что вы можете даже встроить их (но это позволяет вам действительно использовать только 1 байт для хранения и с другой стороны выполнять операции, используя наиболее удобный enum, определенный как вам нравится.

Ответ, который имеет отношение к компилятору ARC (Цитируется по DesignWare MetaWare C / C++ Programmer's Guide for ARC; раздел 11.2.9.2)

Размер перечислений размер типа enum зависит от состояния переключателя *Long_enums*.

■ если переключатель * Long_enums * выключен, тип перечисления сопоставляется с наименьшим из одного, двух или четырех байтов, так что все значения могут быть представлены.

■ если переключатель * Long_enums * включен, перечисление сопоставляется с четыре байта (совпадение соглашение о компиляторе AT&T Portable C).