Подписанные и неподписанные целые числа - PullRequest
358 голосов
/ 29 октября 2008

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

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

Есть другие отличия?

Ответы [ 15 ]

4 голосов
/ 29 октября 2008

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

3 голосов
/ 26 апреля 2014

Знаковые целые числа в C представляют числа. Если a и b являются переменными целочисленных типов со знаком, стандарт никогда не потребует, чтобы компилятор заставил выражение a+=b сохранить в a что-либо кроме арифметической суммы их соответствующих значений. Чтобы быть уверенным, что если арифметическая сумма не поместится в a, процессор может не сможет поместить ее туда, но стандарт не потребует, чтобы компилятор урезал или обернул значение, или сделал бы что-нибудь еще в этом отношении, если значения, которые превышают пределы для их типов. Обратите внимание, что, хотя стандарт не требует этого, реализациям C разрешается перехватывать арифметические переполнения со знаковыми значениями.

Беззнаковые целые числа в C ведут себя как абстрактные алгебраические кольца целых чисел, которые являются конгруэнтными по модулю некоторой степени двух, за исключением сценариев, включающих преобразования или операции с большими типами. Преобразование целого числа любого размера в 32-разрядный тип без знака приведет к члену, соответствующему вещам, которые соответствуют этому целочисленному модулю 4 294 967 296. Причина, по которой вычитание 3 из 2 дает 4 294 967 295, состоит в том, что добавление чего-то равного 3 к чему-то равному 4 294 967 295 даст что-то равное 2.

Абстрактные типы алгебраических колец часто бывают удобны; к сожалению, C использует подпись как решающий фактор того, должен ли тип вести себя как кольцо. Хуже того, значения без знака обрабатываются как числа, а не как члены кольца при преобразовании в более крупные типы, а значения без знака, меньшие int, преобразуются в числа, когда над ними выполняется любая арифметика. Если v является uint32_t, что равно 4,294,967,294, то v*=v; должно составить v=4. К сожалению, если int равен 64 битам, то неясно, что v*=v; может сделать.

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

3 голосов
/ 05 февраля 2011

Целые числа без знака гораздо чаще попадают в конкретную ловушку, чем целые числа со знаком. Эта ловушка связана с тем фактом, что, хотя приведенные выше 1 и 3 верны, обоим типам целых чисел может быть присвоено значение, выходящее за границы того, что оно может "удерживать", и оно будет преобразовано без вывода сообщений.

unsigned int ui = -1;
signed int si = -1;

if (ui < 0) {
    printf("unsigned < 0\n");
}
if (si < 0) {
    printf("signed < 0\n");
}
if (ui == si) {
    printf("%d == %d\n", ui, si);
    printf("%ud == %ud\n", ui, si);
}

Когда вы запустите это, вы получите следующий вывод, даже если оба значения были присвоены -1 и были объявлены по-разному.

signed < 0
-1 == -1
4294967295d == 4294967295d
0 голосов
/ 14 января 2014

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

0 голосов
/ 12 июля 2010

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

...