8-битное перечисление, в C
Мне нужно хранить инструкции, команды, которые я буду получать через последовательный порт.
Команды будут длиной 8 бит.
Мне нужно сохранить прозрачность между именем команды и ее значением.
Чтобы избежать необходимости переводить 8-разрядный номер, полученный в последовательном порядке в любой тип.
Я хотел бы использовать Enumerations, чтобы иметь дело с ними в моем коде.
Только перечисление соответствует а на этой платформе 16-битным целым числом.
Платформа - это микроконтроллер AVR ATmega169V, на демо-панель Butterfly.
Это 8-битная система с ограниченной поддержкой 16-разрядных операций.
Это не быстрая система и имеет около 1 КБ ОЗУ.
В нем нет предметов роскоши, таких как файловый ввод-вывод или операционные системы.
Итак, любые предложения относительно того, какой тип я должен использовать для хранения 8-битных команд?
Там должно быть что-то лучше, чем массивный заголовок #defines.
Ответы
Ответ 1
gcc
-fshort-enums
может быть полезно:
Выделите тип "enum" только как много байтов, как это необходимо для объявленный диапазон возможных значений. В частности, тип "enum" будет эквивалентно наименьший целочисленный тип, который имеет достаточно места.
Фактически здесь страница с большим количеством релевантной информации. Надеюсь, вы столкнулись с множеством переключателей GCC, которых вы никогда не знали.;)
Ответ 2
Вы пытаетесь решить проблему, которая не существует.
Ваш вопрос помечен C. В языках перечисления типа C в контексте значения полностью совместимы с целыми типами и ведут себя точно так же, как и другие интегральные типы. При использовании в выражениях они подвергаются точно таким же интегральным акциям, как и другие интегральные типы. Если учесть это, вы должны понимать, что если вы хотите хранить значения, описанные константами перечисления в 8-битном интегральном типе, все, что вам нужно сделать, это выбрать подходящий общий 8-битный интегральный тип (скажем int8_t
) и использовать его вместо типа перечисления. Вы ничего не потеряете, сохранив ваши постоянные значения enum в объекте типа int8_t
(в отличие от объекта, явно объявленного с типом перечисления).
Описанная вами проблема будет существовать в С++, где типы перечислений разделяются намного дальше от других интегральных типов. В С++ использование интегрального типа вместо типа enum для сохранения памяти сложнее (хотя возможно). Но не в C, где это не требует никаких дополнительных усилий.
Ответ 3
Я не понимаю, почему перечисление не будет работать. Сравнение с и перечислением из перечисления должно отлично работать с расширением по умолчанию. Просто будьте осторожны, чтобы ваши 8-битные значения были правильно подписаны (я бы подумал, что вам понадобится беззнаковое расширение).
Вы получите 16-битные сравнения таким образом, я надеюсь, что это не будет проблемой производительности (этого не должно быть, особенно если ваш процессор 16-битный, как кажется).
Ответ 4
Компилятор Microsoft C позволяет вам делать что-то подобное, но это расширение (стандартное в С++ 0x):
enum Foo : unsigned char {
blah = 0,
blargh = 1
};
Поскольку вы отметили GCC, я не совсем уверен, возможно ли то же самое, но GCC может иметь расширение в режиме gnu99
или что-то в этом роде. Дайте ему вихрь.
Ответ 5
Я бы порекомендовал остаться в enum в любом случае по следующим причинам:
- Это решение позволяет сопоставлять значения команд непосредственно с тем, что ожидает ваш последовательный протокол.
- Если вы действительно используете 16-битную архитектуру, не так много преимуществ для перехода на 8-битный тип. Подумайте о других аспектах, кроме 1 байт памяти.
- В некоторых компиляторах я использовал фактический размер перечисления, используя минимальное количество бит (перечисления, которые могут быть помещены в байты, используются только байты, затем 16 бит, затем 32).
Сначала вам не нужно заботиться о ширине реального типа. Только если вам действительно нужен эффективный способ хранения, вы должны использовать флаги компилятора, такие как -fshort-enums в компиляторе GNU, но я не рекомендую их, если вы им действительно не нужны.
В качестве последней опции вы можете определить "enum" в качестве данных презентации для команд и использовать преобразование в байт с помощью двух простых операций для сохранения/восстановления значения команды в/из памяти (и инкапсулировать это в одном месте). Как насчет этого? Это очень простые операции, поэтому вы можете даже встроить их (но это позволяет вам действительно использовать только 1 байт для хранения и с другой стороны для выполнения операций с использованием большинства используемых перечислений, определенных как вам нравится.
Ответ 6
Ответ, который подходит для компилятора ARC
(Цитируется в DesignWare MetaWare C/С++ Programmers Guide для ARC, раздел 11.2.9.2)
Размер перечислений Размер типа перечисления зависит от статуса переключения * Long_enums *.
■ Если переключатель * Long_enums * выключен, тип перечисления отображает наименьший из одного, двух или четырех байтов, так что все значения могут быть представлены.
■ Если переключатель * Long_enums * включен, перечислимое перечисление четыре байта (соответствующие соглашению AT & T Portable C Compiler).