Когда вы работаете с беззнаковыми типами, модульной арифметикой (также известной как "обтекание" поведение) происходит. Чтобы понять это модульная арифметика , просто взгляните на эти часы:
9 + 4 = 1 ( 13 mod 12 ), поэтому в другом направлении это: 1 - 4 = 9 ( - 3 мод 12 ). Тот же принцип применяется при работе с неподписанными типами. Если тип результата равен unsigned
, то применяется модульная арифметика.
Теперь посмотрите на следующие операции, сохраняющие результат как unsigned int
:
unsigned int five = 5, seven = 7;
unsigned int a = five - seven; // a = (-2 % 2^32) = 4294967294
int one = 1, six = 6;
unsigned int b = one - six; // b = (-5 % 2^32) = 4294967291
Если вы хотите убедиться, что результат равен signed
, сохраните его в переменной signed
или приведите к signed
. Если вы хотите получить разницу между числами и убедиться, что модульная арифметика не будет применена, вам следует рассмотреть возможность использования функции abs()
, определенной в stdlib.h
:
int c = five - seven; // c = -2
int d = abs(five - seven); // d = 2
Будьте очень осторожны, особенно при написании условий, потому что:
if (abs(five - seven) < seven) // = if (2 < 7)
// ...
if (five - seven < -1) // = if (-2 < -1)
// ...
if (one - six < 1) // = if (-5 < 1)
// ...
if ((int)(five - seven) < 1) // = if (-2 < 1)
// ...
но
if (five - seven < 1) // = if ((unsigned int)-2 < 1) = if (4294967294 < 1)
// ...
if (one - six < five) // = if ((unsigned int)-5 < 5) = if (4294967291 < 5)
// ...