Целые числа со знаком и без знака для длины / количества

Для представления переменной длины или счетчика лучше использоватьsigned или жеunsigned целые числа?

Мне кажется, что C ++ STL имеет тенденцию предпочитатьunsigned (std::size_t, как встанд :: вектор :: размер ()вместо C #BCL имеет тенденцию предпочитатьsigned целые числа (как вICollection.Count.

Учитывая, что длина или число являются неотрицательными целыми числами, моя интуиция выберетunsigned; но я не понимаю, почему дизайнеры .NET выбрали целые числа со знаком.

Каков наилучший подход? Каковы плюсы и минусы каждого?

 Joe06 апр. 2012 г., 10:24
Я подозреваю, что C # использует целые числа со знаком, потому чтоunsigned integers are not CLS-compliant.
 IndieProgrammer06 апр. 2012 г., 10:18
Вы должны проверить это:stackoverflow.com/questions/3935165/…
 user130938906 апр. 2012 г., 11:07
@Joe Вы подозреваете правильно. Это в основном потому, что Microsoft хотела распространять"inter-language cooperation", ключевая точка архитектуры их инициативы .NET, общеязыковая среда выполнения. Представление нескольких разновидностей целых чисел просто было неприемлемо из-за проблем совместимости между языками, поэтому оно было объявлено как несовместимое с CLS. Если вы решите использовать их и хотите быть CLS-совместимыми,valued member of society, так сказать. : & # X110;

Ответы на вопрос(4)

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

Естественно использовать неподписанные типы для счетчиков и размеров, если только мы не находимся в каком-то контексте, где они могут быть отрицательными и в то же время иметь смысл. Я предполагаю, что C ++ следует той же логике своего старшего брата C, в которомstrlen() возвращаетсяsize_t а такжеmalloc() принимаетsize_t.

Проблема в C ++ (и C) с целыми числами со знаком и без знака состоит в том, что вы должны знать, как они преобразуются друг в друга, когда вы используете смесь двух видов. Некоторые рекомендуют использовать подписанные целые числа для всего целого, чтобы избежать этой проблемы программистов & apos; невежество и невнимание. Но я думаю, что программисты должны знать, как использовать свои инструменты торговли (языки программирования, компиляторы и т. Д.). Рано или поздно они будут поражены преобразованием, если не тем, что написали, а тем, что есть у кого-то другого. Это неизбежно.

Итак, знайте свои инструменты, выбирайте, что имеет смысл в вашей ситуации.

Здесь есть несколько аспектов:

1) Максимальные значения: обычно максимальное значение числа со знаком равно 1/2 от соответствующего максимального значения без знака. Например, в C максимальное значение короткого знака со знаком равно 32767, тогда как максимальное значение короткого знака без знака равно 65535 (поскольку 1/2 для диапазона -ve не требуется 1/2). Так что, если ваши ожидаемые длины или числа будут большими, представление без знака имеет больше смысла.

2) Безопасность: вы можете просматривать сеть на предмет ошибок целочисленного переполнения, но представьте себе такой код:

if (length <= 100)
{
  // do something with file
}

... тогда если "длина" является значением со знаком, вы рискуете «длина»; быть -ve числом (хотя злонамеренное намерение, некоторое приведение и т. д.) и код не выполняет ожидаемый вами. Я видел это в предыдущем проекте, в котором последовательность увеличивалась для каждой транзакции, но когда целое число со знаком, которое мы использовали, доходило до максимального значения со знаком int (2147483647), оно внезапно становилось -ve после следующего приращения, и наш код не мог обработать Это.

Просто некоторые вещи для размышления, независимо от языка / API.

 14 нояб. 2014 г., 01:47
С другой стороны,while(size-- > 0) является надежной идиомой (хотя в основном в C / C ++, не так много в C #, так как большое внимание уделяется использованию подписанных типов повсюду, что использование неподписанных типов - это больше проблем, чем того стоит, так как вам нужно постоянно выполнять приведение типов). Подписанные типы не спасут плохой код, он будет просто скрывать логические ошибки :)
 06 апр. 2012 г., 17:53
Другая проблема может быть в виде кодаwhile (--size >= 0) ...  когдаsize без знака, условие всегда верно.
Решение Вопроса

C ++ использует беззнаковые значения, потому что им нужен полный диапазон. В 32-битной системе язык должен иметь вектор 4 ГБ, а не только 2 ГБ. (ОС может не позволить вам использовать все 4 ГБ, но сам язык не хочет мешать вам)

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

Тем не менее, это оба крайних случая. Для большинства целей, подписанныйint являетсяbig enough. So as long as both offer the range you need, you can use both.

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

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

Так что на самом деле, это зависит. C ++ использует unsigned, потому что ему нужен диапазон. .NET использует подпись, потому что она должна работать с языками, которые неhave без знака.

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

 06 апр. 2012 г., 11:05
Вы имели в видуUINT_MAX, конечно. Вы можете сравнить свой индекс без знака с размером массива илиINT_MAX чтобы определить переполнения. Больше или равно? Тревога!
 06 апр. 2012 г., 16:55
@jalf: Во-первых, спасибо за отличный ответ. Правильно ли мое понимание - из того, что вы написали - что сsinged целые числаsafer чем с помощьюunsigned? Если так, может быть, BCL использует целые числа со знаком по этой причине помимо ограничений CLS?
 06 апр. 2012 г., 11:22
@ Алекс да, исправил это. и конечно, но размер массива может быть неизвестен. Или это может быть не простая операция индексации, а какая-то другая функция, гдеany положительное число потенциально допустимо, а отрицательное - нет. Дело в том, что иногда есть преимущества для обоих
 06 апр. 2012 г., 18:01
@ Mr_C64: это зависит от контекста. Я просто указалone сценарий, где это может быть безопаснее. Алекс показал другое, где это не имеет никакого значения (и где проверка ошибок на самом деле становится проще с неподписанным int). Вы должны будете подумать об этом сами, для конкретной ситуации, когдаyou нужно это. :)
 06 дек. 2012 г., 16:17
Правда, однако использование unsigned для охвата всего возможного диапазона действительно имело смысл в 16-битных системах, а не в 32-битных. Как только вы приблизитесь к миллиардам элементов, вы также можете использовать 64-битные типы. Отсутствие подписи в повседневном коде привлекает в основном ошибки, предупреждения, беспорядок и боль.

Ваш ответ на вопрос