Тип int по умолчанию: подписанный или неподписанный? - PullRequest
18 голосов
/ 12 октября 2009

При программировании на C-подобном языке должен ли быть целочисленный тип по умолчанию int или uint / unsigned int? По умолчанию я имею в виду, когда вам не нужны отрицательные числа, но любое из них должно быть достаточно большим для данных, которые вы держите. Я могу придумать хорошие аргументы для обоих:

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

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

Ответы [ 7 ]

13 голосов
/ 12 октября 2009

Руководство по стилю Google C ++ 1002 * имеет интересное мнение о целых числах без знака:

(цитата следует:)

На целых числах без знака

Некоторые люди, включая некоторых авторов учебников, рекомендуют использовать неподписанные типы для представления чисел, которые никогда не бывают отрицательными. Это задумано как форма самодокументирования. Однако в Си преимущества такой документации перевешиваются реальными ошибками, которые она может внести. Рассмотрим:

for (unsigned int i = foo.Length()-1; i >= 0; --i) ...

Этот код никогда не прекратит работу! Иногда gcc заметит эту ошибку и предупредит вас, но часто этого не будет. Одинаково плохие ошибки могут возникать при сравнении переменных со знаком и без знака. По сути, схема продвижения типов в C приводит к тому, что неподписанные типы ведут себя иначе, чем можно было бы ожидать.

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

(конец цитаты)

11 голосов
/ 12 октября 2009

Конечно подписано. Если переполнение беспокоит вас, то переполнение должно беспокоить вас больше, потому что случайное падение «ниже нуля» легче, чем через int-max.

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

4 голосов
/ 12 октября 2009

В качестве приблизительного правила я использовал беззнаковые целые для подсчета вещей и подписанные целые для измерения.

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

В моем использовании целые числа без знака предназначены для значений, которые абсолютно не могут стать отрицательными (или для той, что в миллионной ситуации, когда вы на самом деле хотите арифметику по модулю 2 ^ N), а не для значений, которые просто так не оказываются отрицательными, в текущая реализация, вероятно.

3 голосов
/ 12 октября 2009

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

Итак, я не вижу никакой выгоды, если просто установить значение по умолчанию для unsigned, так как обычное int имеет подпись.

2 голосов
/ 12 октября 2009

Вы не получите много «гарантии от переполнения» с неподписанным. Вы, скорее всего, получите другое, но более странное поведение, чем с подписанным, но чуть позже ... Может быть, лучше получить эти предположения прямо перед раздачей?

1 голос
/ 12 октября 2009

Предоставление более конкретного присваивания типа (например, unsigned int) передает больше информации об использовании переменной и может помочь компилятору отслеживать любые случаи, когда вы присваиваете «неправильное» значение. Например, если вы используете переменную для отслеживания идентификатора базы данных объекта / элемента, то (вероятно) никогда не должно быть времени, когда идентификатор меньше нуля (или единицы); в этом случае вместо утверждения этого состояния использование целочисленного значения без знака передает это утверждение другим разработчикам, а также компилятору.

0 голосов
/ 12 октября 2009

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

На языках, которые я использую чаще всего, я использую подпись, если у меня нет особых причин поступать иначе. Это в основном C и C ++. На другом языке я вполне мог бы дать другой ответ.

...