Перечисление C ++ в unsigned int сравнение
-
08-07-2019 - |
Вопрос
Я нашел это в коде, над которым я сейчас работаю, и подумал, что это стало причиной некоторых проблем, с которыми я столкнулся.
В заголовке где-то:
enum SpecificIndexes{
//snip
INVALID_INDEX = -1
};
Потом позже - инициализация:
nextIndex = INVALID_INDEX;
и используйте
if(nextIndex != INVALID_INDEX)
{
//do stuff
}
Отладка кода, значения в nextIndex не совсем имеют смысл (они были очень большими), и я обнаружил, что он был объявлен:
unsigned int nextIndex;
Итак, первоначальная настройка INVALID_INDEX была недостаточной для целого числа unsigned и установила его в огромное число. Я предположил, что это было причиной проблемы, но, если присмотреться, тест
if(nextIndex != INVALID_INDEX)
Вела себя правильно, то есть никогда не выполняла тело оператора if, когда nextIndex был значением "large + ve".
Это правильно? Как это происходит? Является ли значение enum неявным образом приведенным к типу int без знака того же типа, что и переменная, и, следовательно, переносится таким же образом?
Решение
Да ко всему. Это действительный код, он также широко используется библиотечный код C ++, особенно в современном C ++ (это странно, когда вы видите его в первый раз, но в реальности это очень распространенный шаблон).
Тогда перечисления являются подписанными целочисленными значениями, но они неявно преобразуются в неподписанные целые числа, теперь это в зависимости от вашего компилятора может выдавать предупреждение, но оно все еще очень часто используется, однако вы должны явным образом привести приведение, чтобы сделать его понятным сопровождающим. р>
Другие советы
могут быть представлены целочисленными типами со знаком или без знака в зависимости от того, содержат ли они какие-либо отрицательные значения и как чувствует себя компилятор. Этот пример содержит отрицательное значение и, следовательно, должен быть представлен целочисленным типом со знаком.
Сравнение равенства между типами со знаком и без знака является безопасным и обычно выполняет то, что задумал автор - значение со знаком сначала преобразуется в без знака, и результат выполнения определяется стандартом C ++ и интуитивно понятен (по крайней мере, он когда вы знаете тип назначения. За исключением, может быть, если целые числа не являются дополнением к двум. Так что, возможно, это не так интуитивно понятно, но обычно это не вызывает проблем).
Сравнение заказов с большей вероятностью приведет к ошибкам. Например:
SpecificIndexes value = INVALID_VALUE;
return (value >= 0);
возвращает false, но:
unsigned int value = INVALID_VALUE;
return (value >= 0);
возвращает true. Иногда автор не оценит разницу, особенно если указан тип «значение» не совсем так очевидно с точки зрения использования. Однако компилятор может предупредить о втором примере, поскольку (значение > = 0) является тавтологией.
Фактически, -1 неявно приводится к своему эквивалентному значению без знака, когда оно присваивается nextValue. Эквивалентным беззнаковым является значение с таким же побитовым представлением (то есть 111111111111 ... это максимальное значение без знака).
Позднее в операторе сравнения происходит еще одно неявное приведение.
Так что это работает прямо сейчас, но может вызвать проблемы в будущем. Никогда не рекомендуется смешивать значения со знаком и без знака.
Да, я считаю, что перечисления подписаны. Изменить
unsigned int nextIndex;
до
int nextIndex;
и ваша программа должна работать.
Стандарт C ++ позволяет реализации использовать подписанный тип для перечислений, но не требует этого. Следовательно, вы не можете в целом предположить, что в перечисление можно ставить отрицательные числа безопасно.