2008-11-19 13 views
1

Я нашел это в коде, над которым я сейчас работаю, и думал, что это стало причиной некоторых проблем, которые у меня возникают.C++ enum to unsigned int сравнение

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

enum SpecificIndexes{ 
    //snip 
    INVALID_INDEX = -1 
}; 

Тогда позже - инициализации:

nextIndex = INVALID_INDEX; 

и использовать

if(nextIndex != INVALID_INDEX) 
{ 
    //do stuff 
} 

Отладка кода, значения в NEXTINDEX не совсем сделать (они были очень большими), и я обнаружил, что он был объявлен:

unsigned int nextIndex; 

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

if(nextIndex != INVALID_INDEX) 

ведет себя правильно, то есть, он никогда не выполнится тело из если когда NEXTINDEX был «большой анолита значение».

Это правильно? Как это происходит? Является ли значение перечисления неявным образом отличным от неподписанного int того же типа, что и переменная, и, следовательно, обертывается таким же образом?

Приветствия,

Xan

+0

ITYM "Затем более поздняя - сортировка". Инициализация будет `unsigned nextIndex = INVALID_INDEX` – MSalters 2008-11-20 12:50:58

ответ

11

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

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

1

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

Позже, в инструкции сравнения, происходит другое неявное литье.

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

+0

А как насчет теста с значением перечисления, я предполагаю, что это тоже неявный литье? – xan 2008-11-19 11:36:32

+0

Как раз для записи, я согласился с точкой хэна и отредактировал свою запись соответственно. Но я не знаю, почему мой комментарий исчез. – Gorpik 2008-11-19 14:40:22

+0

«Эквивалентное значение без знака - это значение с тем же поразрядным представлением» - это верно, если в реализации используется представление с двумя дополнениями для подписанных интегральных типов. Однако это не определение, и это неверно для представлений об одном дополнении или знаке. В любом случае они редки. – 2008-11-21 13:13:41

0

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

unsigned int nextIndex; 

в

int nextIndex; 

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

2

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

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

Сравнение заказов, скорее всего, приведет к ошибкам. Например:

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

возвращает ложное, но:

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

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

0

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