У чому різниця між підписаним та безпідписаним int


91

Яка різниця між підписаним та безпідписаним int?


5
Це справжнє запитання, і відповідь не така проста, а досить тонка.
R .. GitHub СТОП ДОПОМОГАЙ ЛЕД

Голосування за відновлення. Це може бути дублікат, але це, безумовно, справжнє питання.
Брайан,


Слід додати більше тегів, оскільки багато мов використовують їх.
Хуан Боеро,

Для детального розробки цього питання може знадобитися глава. Якщо ви хочете дізнатися про тонкощі та недоліки, ознайомтесь із пунктами Непідписані та Підписані цілі числа для отримання додаткових пояснень.
анонімно

Відповіді:


113

Як вам, мабуть, відомо, ints зберігаються всередині двійкового файлу. Зазвичай an intмістить 32 біта, але в деяких середовищах може містити 16 або 64 біта (або навіть інше число, як правило, але не обов'язково степеня два).

Але для цього прикладу давайте розглянемо 4-бітові цілі числа. Крихітний, але корисний для ілюстративних цілей.

Оскільки в такому цілому числі є чотири біти, воно може приймати одне з 16 значень; 16 дорівнює двом до четвертого степеня, або 2 рази 2 рази 2 рази 2. Які це значення? Відповідь залежить від того, чи є це ціле число a signed intабо an unsigned int. При an unsigned intзначення ніколи не є від’ємним; немає знака, пов’язаного зі значенням. Ось 16 можливих значень чотирибітових unsigned int:

bits  value
0000    0
0001    1
0010    2
0011    3
0100    4
0101    5
0110    6
0111    7
1000    8
1001    9
1010   10
1011   11
1100   12
1101   13
1110   14
1111   15

... і ось 16 можливих значень чотирибітових signed int:

bits  value
0000    0
0001    1
0010    2
0011    3
0100    4
0101    5
0110    6
0111    7
1000   -8
1001   -7
1010   -6
1011   -5
1100   -4
1101   -3
1110   -2
1111   -1

Як бачите, для signed ints найбільш значущим бітом є 1тоді і тільки тоді, коли число від’ємне. Ось чому для signed ints цей біт відомий як "знаковий біт".


11
Можливо, варто зазначити, що це формат доповнення двох, який, правда, сьогодні широко використовується. Існують також інші способи представлення підписаних цілих чисел, зокрема, доповнення.
Шедлер

Правильно. А стандарт ISO9899 C навіть не вимагає, щоб використовувався або один, або два доповнення; будь-яка інша конвенція, яка насправді працює, є допустимою.
Білл Еванс у Mariposa

1
Незважаючи на те, що доповнення двох не потрібно, (unsigned)(-1)потрібно, щоб це було максимально репрезентабельне значення для unsigned(незалежно від двійкового подання), що тривіально вірно для доповнення 2, але не для інших подань.
rubenvb

3
@BillEvansatMariposa: Стандарт говорить, що для підписаних цілих чисел є 3 дозволених подання: знак + величина, доповнення 2, доповнення 1. Будь-який інший повинен бути невидимим для програми і сприйматися як один із цих 3.
Олексій Фрунзе

Гаразд, але під капотом! Що РЕАЛЬНО відбувається! Яка різниця між ПІДПИСАНИМ і НЕПОДПИСАНИМ номером! Як машина керує обчисленнями? Це просто віднімає значення з іншого? Як це відрізняється 1111 = 15 та 1111 = -1?
Михайло Георгеску

19

intі unsigned intє двома різними цілими типами. ( intможе також позначатися як signed intабо просто signed; unsigned intтакож може позначатися як unsigned.)

Як випливає з назв, intце цілий тип із підписом і цілий тип unsigned intбез підпису . Це означає, що intвін здатний представляти від’ємні значення і unsigned intможе представляти лише невід’ємні значення.

Мова С накладає деякі вимоги до діапазонів цих типів. Діапазон intповинен бути принаймні -32767.. +32767, а діапазон unsigned intповинен бути принаймні 0.. 65535. Це означає, що обидва типи повинні мати принаймні 16 біт. У багатьох системах вони складають 32 біти, а в деяких - навіть 64 біти. intяк правило, має додаткове негативне значення через представлення доповнення двох, що використовується більшістю сучасних систем.

Мабуть, найважливішою відмінністю є поведінка арифметики зі знаком та без знака. Для підписаного intпереповнення має невизначену поведінку. Бо unsigned intнемає переповнення; будь-яка операція, яка дає значення поза діапазоном типу, обертається, наприклад, наприклад UINT_MAX + 1U == 0U.

Будь-який цілий тип, підписаний чи беззнаковий, моделює піддіапазон нескінченного набору математичних цілих чисел. Поки ви працюєте зі значеннями в діапазоні типу, все працює. Коли ви наближаєтесь до нижньої або верхньої межі типу, ви стикаєтесь із розривом, і ви можете отримати несподівані результати. Для підписаних цілих типів проблеми виникають лише для дуже великих від'ємних і додатних значень, що перевищують INT_MINі INT_MAX. Для цілих типів без знаку проблеми виникають при дуже великих додатних значеннях і при нулі . Це може бути джерелом помилок. Наприклад, це нескінченний цикл:

for (unsigned int i = 10; i >= 0; i --) [
    printf("%u\n", i);
}

тому що iце завжди більше або дорівнює нулю; така природа непідписаних типів. (Усередині циклу, коли iдорівнює нулю, i--встановлюється його значення UINT_MAX.)


12

Іноді ми заздалегідь знаємо, що значення, яке зберігається у даній цілочисельній змінній, завжди буде позитивним - коли воно використовується лише для підрахунку речей, наприклад. У такому випадку ми можемо оголосити змінну , щоб бути без знака, як і в, unsigned int num student;. При такому оголошенні діапазон допустимих цілочисельних значень (для 32-розрядного компілятора) зміститься від діапазону -2147483648 до +2147483647 до діапазону від 0 до 4294967295. Таким чином, оголошення цілого числа без знаку майже подвоює розмір найбільшого з можливих значення, яке воно може мати в іншому випадку.


@Alex Я був посеред редагування цієї відповіді 10 хвилин тому, і це ідентично. lol
Skuld

12

Якщо говорити непрофесійно, беззнаковий int - це ціле число, яке не може бути від'ємним і, отже, має вищий діапазон позитивних значень, який він може прийняти. Підписаний int - це ціле число, яке може бути від’ємним, але має нижчий позитивний діапазон в обмін на більше від’ємних значень, які він може прийняти.


0

На практиці є дві відмінності:

  1. друк (наприклад, coutна C ++ або printfна C): беззнакове ціле бітове подання інтерпретується як невід’ємне ціле число функціями друку.
  2. замовлення : замовлення залежить від специфікації, що підписана або не підписана.

цей код може ідентифікувати ціле число за допомогою критерію упорядкування:

char a = 0;
a--;
if (0 < a)
    printf("unsigned");
else
    printf("signed");

Якщо це пояснювало різне, якщо одна ділиться негативними числами, а інша - ні. Це дуже допомогло б цій публікації.
Деніел Джексон

@DanielJackson Незрозуміло, що ви говорите. символ можна вважати негативним або позитивним залежно від компілятора. вихід коду залежить від того, що вибрав компілятор, і це показує різницю між підписаним та безпідписаним.
Minimus Heximus
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.