Ответ - да.Тип unsigned int в C и C ++ не является «всегда положительным целым числом», независимо от того, как выглядит имя типа.Поведение C / C ++ беззнаковых целочисленных значений не имеет смысла, если вы пытаетесь прочитать тип как «неотрицательный» ... например:
- Разница между двумя беззнаковыми числами является числом без знака (делаетне имеет смысла, если вы читаете это как «Разница между двумя неотрицательными числами неотрицательна»)
- Добавление целого и беззнакового целого является беззнаковым
- Существует неявное преобразованиеот int до unsigned int (если вы читаете unsigned как «неотрицательное», это имеет смысл противоположное преобразование, которое имеет смысл)
- Если вы объявляете функцию, принимающую параметр без знака, когда кто-то передаетОтрицательный int вы просто неявно преобразуете в огромное положительное значение;другими словами, использование типа параметра без знака не помогает вам находить ошибки ни во время компиляции, ни во время выполнения.
Действительно, числа без знака очень полезны для определенных случаев, потому что они являются элементами целых чисел кольца-модуло-N "с N, являющимся степенью двойки.Целые числа без знака полезны, когда вы хотите использовать эту арифметику по модулю или как битовые маски;они НЕ полезны в качестве величин.
К сожалению, в C и C ++ без знака также использовались для представления неотрицательных величин, чтобы иметь возможность использовать все 16 битов, когда целые числа были такими маленькими ... в то времяиспользовать 32k или 64k считалось большой разницей.Я бы классифицировал это в основном как историческую случайность ... вы не должны пытаться читать логику, потому что там не было логики.
Кстати, по моему мнению, это было ошибкой ... если32 КБ недостаточно, тогда довольно скоро 64 КБ тоже будет недостаточно;злоупотребление целым числом по модулю только из-за одного дополнительного бита, по моему мнению, было слишком дорого, чтобы заплатить.Конечно, было бы разумно сделать это, если бы присутствовал или был определен надлежащий неотрицательный тип ... но беззнаковая семантика просто неверна для использования его как неотрицательного.
Иногда вы можете найти, кто говоритэтот unsigned хорош, потому что он «документирует», что вам нужны только неотрицательные значения ... однако эта документация имеет какое-либо значение только для людей, которые на самом деле не знают, как unsigned работает для C или C ++.Для меня видение беззнакового типа, используемого для неотрицательных значений, просто означает, что тот, кто написал код, не понимал язык этой части.
Если вы действительно понимаете и хотите"упаковку"«поведение неподписанных целых чисел, тогда они являются правильным выбором (например, я почти всегда использую« беззнаковый символ », когда я обрабатываю байты);если вы не собираетесь использовать поведение обтекания (и это поведение будет для вас проблемой, как в случае разницы, которую вы показали), то это явный показатель того, что неподписанный тип является плохим выбором, и выследует придерживаться простых целочисленных значений.
Означает ли это, что возвращаемый тип C ++ std::vector<>::size()
является плохим выбором?Да ... это ошибкаНо если вы так говорите, будьте готовы к тому, что вас будут называть дурными именами, которые не понимают, что «беззнаковое» имя - это просто имя ... то, что оно считает, - это поведение, а это - «по модулю n» (и неможно было бы считать «по модулю n» тип контейнера разумным выбором.