Вопрос

Я нашел это в коде, над которым я сейчас работаю, и подумал, что это стало причиной некоторых проблем, с которыми я столкнулся.

В заголовке где-то:

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 ++ позволяет реализации использовать подписанный тип для перечислений, но не требует этого. Следовательно, вы не можете в целом предположить, что в перечисление можно ставить отрицательные числа безопасно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top