Когда использовать беззнаковые значения вместо подписанных?

Когда уместно использовать беззнаковую переменную вместо подписанной? А как насчет for петли?

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

for (unsigned int i = 0; i < someThing.length(); i++) {  
    SomeThing var = someThing.at(i);  
    // You get the idea.  
}

Я знаю, что в Java нет значений без знака, и это должно быть осознанное решение со стороны Sun Microsystems .

Ответов (5)

Решение

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

Таким образом, подписанный - хороший общий выбор - даже если вы абсолютно уверены, что все числа положительны, - если вы собираетесь выполнять арифметические операции с переменной (как в типичном случае цикла for).

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

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

size_t часто является хорошим выбором для этого, или size_type если вы используете класс STL.

В приведенном выше примере, когда «i» всегда будет положительным и более высокий диапазон будет полезен, будет полезен беззнаковый. Например, если вы используете операторы объявления, например:

#declare BIT1 (unsigned int 1)
#declare BIT32 (unsigned int reallybignumber)

Особенно, когда эти значения никогда не изменятся.

Однако, если вы выполняете бухгалтерскую программу, в которой люди безответственны со своими деньгами и постоянно находятся в минусе, вы определенно захотите использовать «подписанный».

Я действительно согласен с saint, что хорошее практическое правило - использовать подписанный, что на самом деле C по умолчанию, так что вы защищены.

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

Естественно, вы компилируете с полностью перевернутыми предупреждениями, не так ли?

И не думали ли вы о компиляции с «обработкой предупреждений как ошибок», чтобы сделать еще один шаг вперед?

Обратной стороной использования чисел со знаком является соблазн перегрузить их так, чтобы, например, значения 0-> n были выбором меню, а -1 означало, что ничего не выбрано - вместо того, чтобы создавать класс, который имеет две переменные, от одной до указать, если что-то выбрано, а другое - сохранить, что это за выбор. Прежде чем вы это узнаете, вы повсюду проверяете отрицательный результат, а компилятор жалуется на то, как вы хотите сравнить выбор меню с количеством имеющихся у вас вариантов меню - но это опасно, потому что они разных типов. . Так что не делай этого.

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

Имея это в виду, я только недавно узнал о целых числах без знака, когда работал над проектом, обрабатывая данные в двоичном файле и сохраняя данные в базе данных. Я намеренно «испортил» двоичные данные и в итоге получил отрицательные значения вместо ожидаемой ошибки. Я обнаружил, что даже несмотря на то, что значение было преобразовано, оно не соответствовало моему бизнес-сценарию.
Моя программа не вызвала ошибок, и в итоге я получил неправильные данные в базе данных. Было бы лучше, если бы я использовал uint и программу не удалось.