Підписані цілі числа в C представляють числа. Якщо a
і b
є змінними цілих цілочисельних типів, стандарт ніколи не вимагатиме, щоб компілятор перетворив запас виразів a+=b
у a
щось інше, ніж арифметична сума їх відповідних значень. Щоб бути впевненим, якщо арифметична сума не вміститься a
, процесор може не змогти її помістити, але стандарт не вимагає від компілятора усікання або перенесення значення або робити щось інше з цього питання, якщо значення перевищують межі для їх видів. Зауважте, що, хоча стандарт цього не вимагає, реалізаціям 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;
можна зробити.
З огляду на стандартний такий, який він є, я б запропонував використовувати непідписані типи в ситуаціях, коли хочеться поведінки, пов'язаної з алгебраїчними кільцями, і підписаних типів, коли потрібно представляти числа. Прикро, що С намалював відзнаки так, як це зробив, але вони є такими, якими вони є.