10

手册页中指出了这一点的负面影响:

NOTES 没有定义试图取最大负整数的绝对值。

这背后的原因是什么?对于想要避免未定义行为的人来说,最好的办法是什么?我是否必须求助于:

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

(故意 hacky 以强调对 stdlib 的不满 ;-)

例子

假设您有一个 4 位有符号值(为了便于理解)。无符号最大值为 15,有符号(正)最大值为 7,有符号(负)最小值为 -8,因此 abs(-8) 不适合有符号值。当然,您可以将其表示为 -8,但是结果的除法和乘法不能按预期工作。

4

2 回答 2

19

这个问题的真正答案在于类型提升规则。

如果我对 anunsigned int和 an应用算术运算符int,则int参数将提升为unsigned,结果也是unsigned

如果abs()函数返回unsigned,那么在表达式中使用时会导致其他值的这种类型提升,从而导致意外结果。例如,这段代码:

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

会打印 ">= 0",这是很多人不喜欢的。不能使用 single value 的折衷INT_MIN可能看起来不错。

于 2009-10-23T04:05:52.100 回答
0

为什么它会使用无符号空间返回一个值?

让我们考虑 8 位有符号和无符号数字。如果你有-128,结果是未定义的......我猜stdlib不想让事情减慢那么多。如果您认为您可能有该范围内的数字,那么您需要使用其他东西。

如果您认为您的签名字符中的值可能大于 127,那么您就错了。

因此,该值没有必要能够保持大于 127 的值,并且保持签名不会丢失任何内容。如果您想将其转换为未签名,请继续。由于它曾经只是一个有符号整数,因此您很有可能再次进行有符号数学运算。就个人而言,我认为我更喜欢类型保持有符号,因为我实际上想要处理无符号并且我不进行位操作的情况非常罕见。

但也许其他人可以从标准委员会那里挖出一些笔记。

于 2009-10-23T01:31:09.587 回答