Почему семейство функций stdlib.h abs () возвращает значение со знаком? - PullRequest
10 голосов
/ 23 октября 2009

Отрицательный смысл этого отмечен на странице руководства:

ПРИМЕЧАНИЯ Попытка взять абсолютное значение наиболее отрицательного целого числа не определены.

В чем причина этого и что является лучшим выходом для человека, который хотел бы избежать неопределенного поведения? Должен ли я прибегнуть к чему-то вроде:

unsigned uabs(signed val) {
    return val > 0
        ? val
        : (val == 1U << ((sizeof(val) * 8) - 1))
            ? -1U
            : -val;
}

(Намеренно хаки, чтобы подчеркнуть неудовольствие с помощью stdlib; -)

Пример

Скажем, у вас есть 4-битное значение со знаком (для простоты понимания). Максимальное значение без знака равно 15, максимальное значение со знаком (положительное значение) равно 7, минимальное значение со знаком (отрицательное значение) равно -8, поэтому значение abs (-8) не будет соответствовать значению со знаком. Конечно, вы можете представить его как -8, но тогда деление и умножение с результатом не будут работать, как ожидалось.

Ответы [ 2 ]

19 голосов
/ 23 октября 2009

Реальный ответ на этот вопрос заключается в правилах продвижения типа.

Если я применяю арифметический оператор к unsigned int и int, то аргумент int переводится в unsigned, и результат также равен unsigned.

Если функция abs() вернула unsigned, то это вызвало бы такой тип продвижения типов других значений при использовании в выражении, что привело бы к неожиданным результатам. Например, этот код:

if (abs(-1) * -1 < 0)
    printf("< 0\n");
else
    printf(">= 0\n");

Выведет "> = 0", что многим не понравится. Компромисс из-за невозможности использовать единственное значение INT_MIN, по-видимому, казался нормальным.

0 голосов
/ 23 октября 2009

Зачем ему возвращать значение с использованием беззнакового пробела?

Давайте рассмотрим 8-битные числа со знаком и без знака. Если у вас есть -128, результат не определен ... Я думаю, что stdlib не хочет слишком сильно тормозить. Если вы думаете, что у вас может быть число в этом диапазоне, тогда вам нужно использовать что-то еще.

Если вы считаете, что в подписанном символе может быть значение больше 127, то вы ошибаетесь.

Следовательно, необязательно, чтобы значение могло содержать значение больше 127, а сохранение его в подписи ничего не теряет. Если вы хотите сделать это без знака, продолжайте. Так как раньше это было целое число со знаком, есть вероятность, что вы снова будете выполнять математику со знаком. Лично я думаю, что предпочел бы, чтобы тип оставался подписанным, поскольку я редко хочу иметь дело с неподписанным, и я не выполняю битовые операции.

Но, может быть, кто-то еще сможет почерпнуть некоторые заметки из комитета по стандартам.

...