Перечисления C ++ подписаны или неподписаны? Кроме того, безопасно ли проверять ввод, проверяя, что это <= ваше максимальное значение, и не учитывать> = ваше минимальное значение (при условии, что вы начали с 0 и увеличили на 1)?
107
Ответы:
Вы не должны полагаться на какое-либо конкретное представление. Прочтите следующую ссылку . Кроме того, в стандарте говорится, что это определяется реализацией, какой интегральный тип используется в качестве базового типа для перечисления, за исключением того, что он не должен быть больше, чем int, если какое-то значение не может поместиться в int или беззнаковое int.
Вкратце: вы не можете полагаться на то, что перечисление подписано или неподписано.
источник
Пойдем к первоисточнику. Вот что говорится в документе стандарта C ++ 03 (ISO / IEC 14882: 2003) в 7.2-5 (Объявления перечисления):
Короче говоря, ваш компилятор может выбирать (очевидно, если у вас есть отрицательные числа для некоторых значений перечисления, они будут подписаны).
источник
Вы не должны зависеть от того, подписаны они или нет. Если вы хотите сделать их явно подписанными или неподписанными, вы можете использовать следующее:
источник
Вы не должны полагаться на то, что он подписан или неподписан. Согласно стандарту это определяется реализацией, какой интегральный тип используется в качестве базового типа для перечисления. Однако в большинстве реализаций это целое число со знаком.
В C ++ 0x будут добавлены строго типизированные перечисления , которые позволят вам указать тип перечисления, например:
Однако даже сейчас можно выполнить простую проверку, используя перечисление в качестве типа переменной или параметра, например:
источник
Компилятор может решить, подписаны ли перечисления или нет.
Другой метод проверки перечислений - использовать само перечисление как тип переменной. Например:
источник
Даже некоторые старые ответы получили 44 положительных голоса, я склонен не соглашаться со всеми из них. Короче говоря, я не думаю, что нам следует заботиться о
underlying type
перечислении.Во-первых, тип Enum в C ++ 03 - это отдельный тип, не имеющий понятия знака. Поскольку из стандарта C ++ 03
dcl.enum
Поэтому, когда мы говорим о знаке типа перечисления, скажем, при сравнении двух операндов перечисления с использованием
<
оператора, мы фактически говорим о неявном преобразовании типа перечисления в некоторый целочисленный тип. Важен только знак этого интегрального типа . И при преобразовании enum в целочисленный тип применяется следующее утверждение:И, по-видимому, основной тип перечисления не имеет ничего общего с Integral Promotion. Поскольку стандарт определяет интегральное продвижение следующим образом:
Итак, становится ли перечисление типом
signed int
илиunsigned int
зависит от того,signed int
может ли он содержать все значения определенных перечислителей, а не базовый тип перечисления.См. Мой связанный вопрос Признак неправильного типа перечисления C ++ после преобразования в интегральный тип
источник
-Wsign-conversion
. Мы используем его, чтобы выявлять непреднамеренные ошибки в нашем коде. Но +1 за ссылку на стандарте, и указывая на то , что перечисление не имеет типа ( поsigned
сравнениюunsigned
) , связанный с ним.В будущем с C ++ 0x будут доступны строго типизированные перечисления, которые будут иметь несколько преимуществ (например, безопасность типов, явные базовые типы или явное определение области видимости). Благодаря этому вы могли бы лучше быть уверены в знаке типа.
источник
В дополнение к тому, что другие уже говорили о подписанном / неподписанном, вот что стандарт говорит о диапазоне перечислимого типа:
7.2 (6): «Для перечисления, где e (min) - наименьший перечислитель, а e (max) - наибольший, значения перечисления - это значения базового типа в диапазоне от b (min) до b (max ), где b (min) и b (max) - соответственно наименьшее и наибольшее значения наименьшего битового поля, которое может хранить e (min) и e (max). Можно определить перечисление, значения которого не определены любым из его счетчиков ".
Так например:
определяет перечислимый тип, где e (min) равно 1, а e (max) равно 4. Если базовый тип подписан int, то наименьшее требуемое битовое поле имеет 4 бита, и если целые числа в вашей реализации являются двумя дополнениями, тогда допустимый диапазон перечисление составляет от -8 до 7. Если базовый тип беззнаковый, то он имеет 3 бита, а диапазон - от 0 до 7. Если вас это интересует, проверьте документацию по компилятору (например, если вы хотите привести целые значения, отличные от перечислителей, к перечислимого типа, тогда вам нужно знать, находится ли значение в диапазоне перечисления или нет - если нет, результирующее значение перечисления не указано).
Вопрос о том, являются ли эти значения допустимыми входными данными для вашей функции, может отличаться от того, являются ли они допустимыми значениями перечисляемого типа. Ваш проверочный код, вероятно, беспокоится о первом, а не о втором, поэтому в этом примере следует, по крайней мере, проверять> = A и <= B.
источник
Проверьте это с помощью
std::is_signed<std::underlying_type
перечислений + scoped enums по умолчаниюint
https://en.cppreference.com/w/cpp/language/enum подразумевает:
main.cpp
GitHub вверх по течению .
Скомпилируйте и запустите:
Вывод:
Проверено на Ubuntu 16.04, GCC 6.4.0.
источник