Ответ 1
Сначала можно применить к неподписанному варианту. Это обеспечивает четкое поведение. Если вместо этого код выглядит следующим образом:
unsigned long abs(long input)
{
if (input >= 0)
{
// input is positive
return static_cast<unsigned long>(input);
}
else
{
return -static_cast<unsigned long>(input); // read on...
}
}
мы вызываем две четко определенные операции. Преобразование целочисленного знака в неподписанное значение определено N3485 4.7 [conv.integral]/2:
Если тип назначения не указан, результирующее значение представляет собой наименьшее целое без знака, сравнимое с исходным целым числом (по модулю 2 ^ n, где n - количество бит, используемых для представления неподписанного типа). [Примечание. В представлении с двумя дополнениями это преобразование является концептуальным и нет изменений в битовой схеме (если нет усечения). - конечная нота]
В основном это говорит о том, что при выполнении конкретного преобразования перехода от подписанного к беззнаковому можно предположить, что обход без знака.
Отрицание целого числа без знака хорошо определено в 5.3.1 [expr.unary.op]/8:
Отрицание неподписанной величины вычисляется путем вычитания его значения из 2 ^ n, где n - количество бит в продвинутом операнде.
Эти два требования эффективно заставляют реализации работать как машина с дополнением 2s, даже если базовая машина является 1s-дополнением или сигнальной машиной.