man页中指出了这种情况的负面影响:
注意事项 尝试获取最小负整数的绝对值是未定义的。
为什么会这样?有何最佳解决方案可以避免未定义行为?我是否必须采取以下措施:
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,但是对结果进行除法和乘法会产生预期之外的结果。
INT_MIN
,如果您将其传递给abs()
。 - cafint
的一种类型,你永远不必检查某些东西是否低于INT_MIN
,所以在这个特定的unsigned abs(signed)
情况下,在调用之前根本不需要检查参数。 - cdlearyINT_MIN
- 相反,你需要检查计算结果是否会低于INT_MIN
(因为这会导致有符号溢出,这是未定义的行为)。例如,如果你正在计算a-b
,在正常情况下,你需要验证a>=INT_MIN+b
- 如果你要将其传递给abs()
,则需要将其更改为a>INT_MIN+b
。 - caf