Правильно ли теперь рассчитывается расстояние между двумя длинными знаками стандартным и переносимым способом?
Да.
Редкое исключение 1 обязало бы использовать более широкий тип.
Рассмотрим 3 случая, когда x > y
x>= 0, y> = 0
Следующее является тривиально правильным, так как приведение не меняет значение .
(unsigned long)x - (unsigned long)y
x <0,y <0 </strong>
Оба значения x, y увеличиваются на ULONG_MAX + 1
из-за (unsigned long)
, и вычитание отменяет это.
// is akin to
((unsigned long)(x + ULONG_MAX + 1) - (unsigned long)(y + ULONG_MAX + 1))
// or
x - y // with unsigned math.
x>= 0, y <0 </strong>
(unsigned long)y
имеет значение y + ULONG_MAX + 1
, что больше x
.(Предполагая ULONG_MAX/2 >= LONG_MAX
1 ) Разница отрицательная.Тем не менее unsigned математика оборачивается и добавляет обратно ULONG_MAX + 1
.
// is akin to
((unsigned long)x - (unsigned long)(y + ULONG_MAX + 1)) + (ULONG_MAX + 1).
// or
x - y // with unsigned math.
x <0, y> = 0
Этот случайневозможно, так как x > y
.
1 : C не указывает ULONG_MAX/2 == LONG_MAX
, хотя это чрезвычайно распространено.Я только сталкивался с этим однажды давным-давно, где это не применимо.В этом случае это было ULONG_MAX == LONG_MAX
.ULONG_MAX/2 == LONG_MAX
настолько ожидаемо, что я сомневаюсь, что современная платформа рискнула бы этого не делать.C определяет ULONG_MAX >= LONG_MAX
.
Диапазон неотрицательных значений целого типа со знаком является поддиапазоном соответствующего целого типа без знака, и представление одного и того же значения в каждом типе одинаково.... C11dr §6.2.5 9
Код может использовать приведенное ниже для обнаружения этих редких платформ.
#if ULONG_MAX/2 < LONG_MAX
#error `unsigned long` too narrow. Need new approach.
#endif