Перечисления были добавлены к языку C с опозданием. Как следствие, они не являются «строго типизированными» - C мало чем отличается от guish их от других целочисленных значений, и поэтому они во многом удобны.
В теории, Вы можете объявить объект типом перечисления, чтобы указать, что он должен содержать некоторое значение из перечисления, а не любое другое. Стандарт C не требует его применения. Некоторые компиляторы могут предупреждать о нарушениях этого при некоторых обстоятельствах, но они не могут отловить их все.
Каждый идентификатор в перечислении имеет значение int
. Из-за этого люди используют их как способ определения констант времени компиляции. Часто это простые последовательные константы, например, для числа дней недели, но они также могут быть произвольными константами, такими как битовые маски или адреса памяти (в пределах диапазона int
). Это не является их истинным назначением, но это то, для чего они полезны, поэтому люди используют его.
Тип перечисления и любые объекты, определенные для него, такие как то, что вы объявляете enum day today
, должны иметь тип совместим с некоторым целочисленным типом. Например, если все значения в перечислении находятся в диапазоне char
, тип перечисления может фактически составлять char
. Это означает, что в структуре может потребоваться меньше места, чем при объявлении int
. Однако стандарт C не требует, чтобы компилятор использовал наименьший целочисленный тип, который подходит, поэтому эта функция бесполезна для того, чтобы полагаться на перечисления для ограничения используемого пространства.
Стандарт C также не делает требовать каких-либо предупреждений, когда некоторому общему целочисленному значению присваивается объект перечисления. При существующем дизайне перечислений это на самом деле невозможно - поскольку идентификаторы перечисления являются int
значениями, правая часть любого присваивания, которое их использует, как в today = Monday + 1
, является, по крайней мере, int
, не совсем ясно, значение в перечислении, и компилятору становится трудно диагностировать проблемы.
Из-за этих слабых правил перечисления не существует строгого правила определения объектов как типов перечисления, а не, скажем, , int
или char
. Можно было бы sh определить что-то, чтобы быть типом перечисления, чтобы передать будущим читателям исходного кода, что это используется для записи вещей в этом типе перечисления, но можно также определить sh, чтобы определить это как uint8_t
, чтобы гарантировать использование только одного байта в массиве или структуре. Таким образом, существуют противоречивые причины для выбора, и автору придется выбирать один или другой.
В общем случае, если вы просто используете перечисление в коде для хранения и работы со значениями перечисления, и он не является частью массива, структуры или другой вещи, где пространство имеет большое значение, а затем определите его, используя тип перечисления. Это наилучшим образом передает читателю и компилятору ваше намерение.