Перечисление c ++ в unsigned int сравнение - PullRequest
1 голос
/ 19 ноября 2008

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

В шапке где-то:

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 без знака того же типа, что и переменная, и, следовательно, переносится таким же образом?

Приветствия

1024 * Xan *

Ответы [ 5 ]

11 голосов
/ 19 ноября 2008

Да всем. Это действительный код, он также обычно используется на библиотечном C ++-коде, особенно в современном C ++ (странно, когда вы видите его в первый раз, но в реальности это очень распространенный шаблон).

Тогда перечисления являются подписанными целочисленными значениями, но они неявно преобразуются в неподписанные целые числа, теперь это в зависимости от вашего компилятора может выдавать предупреждение, но оно все еще очень часто используется, однако вы должны явным образом привести приведение к нему для сопровождающих. *

2 голосов
/ 21 ноября 2008

перечисления могут быть представлены целыми типами со знаком или без знака в зависимости от того, содержат ли они какие-либо отрицательные значения и как чувствует себя компилятор. Этот пример содержит отрицательное значение и, следовательно, должен быть представлен целочисленным типом со знаком.

Сравнение равенства между типами со знаком и без знака безопасно и, как правило, выполняет то, что задумал автор - значение со знаком сначала преобразуется в без знака, и результат выполнения определяется стандартом C ++ и является интуитивным когда вы знаете тип назначения. За исключением, может быть, если целые числа не являются дополнением к двум. Так что, возможно, это не так интуитивно понятно, но обычно это не вызывает проблем).

Сравнение заказов с большей вероятностью приведет к ошибкам. Например:

SpecificIndexes value = INVALID_VALUE;
return (value >= 0);

возвращает false, но:

unsigned int value = INVALID_VALUE;
return (value >= 0);

возвращает истину. Иногда автор не оценит разницу, особенно если тип «стоимости» не так очевиден с точки зрения использования. Однако компилятор может предупредить о втором примере, поскольку (значение> = 0) является тавтологией.

1 голос
/ 19 ноября 2008

Фактически, -1 неявно приводится к своему эквивалентному значению без знака, когда оно присваивается nextValue. Эквивалентным беззнаковым является значение с таким же побитовым представлением (то есть 111111111111 ... это максимальное значение без знака).

Позже в операторе сравнения происходит другое неявное приведение.

Так что это работает прямо сейчас, но может вызвать проблемы в будущем. Никогда не рекомендуется смешивать значения со знаком и без знака.

0 голосов
/ 28 февраля 2012

Стандарт C ++ позволяет реализации использовать подписанный тип для перечислений, но не требует этого. Следовательно, вы не можете в целом предположить, что в перечисление можно ставить отрицательные числа безопасно.

0 голосов
/ 19 ноября 2008

Да, я считаю, что перечисления подписаны. Изменить

unsigned int nextIndex;

до

int nextIndex;

и ваша программа должна работать.

...