手册中注明了这种负面含义:
注意未定义尝试取最负整数的绝对值.
这背后的原因是什么?对于想避免未定义行为的人来说,最好的办法是什么?我是否必须采取以下措施:
unsigned uabs(signed val) {
return val > 0
? val
: (val == 1U << ((sizeof(val) * 8) - 1))
? -1U
: -val;
}
Run Code Online (Sandbox Code Playgroud)
(故意hacky强调对stdlib的不满;-)
假设您有一个4位有符号值(为了便于理解).unsigned max是15,signed(正)max是7,signed(负)min是-8,所以abs(-8)不适合有符号值.当然,您可以将其表示为-8,但随后对结果进行除法和乘法不会按预期工作.
caf*_*caf 19
这个问题的真正答案在于类型提升规则.
如果我将算术运算符应用于a unsigned int和a int,则int参数将被提升为unsigned,结果也是unsigned.
如果abs()函数返回unsigned,那么当它在表达式中使用时会导致其他类型的类型提升,这会导致意外的结果.例如,这段代码:
if (abs(-1) * -1 < 0)
printf("< 0\n");
else
printf(">= 0\n");
Run Code Online (Sandbox Code Playgroud)
会打印"> = 0",这是许多人不喜欢的.无法使用单一值的权衡INT_MIN可能看起来不错.