正确获取INT_MIN的绝对值的方法

我想在unsigned中执行一些算术,并且需要采用负int的绝对值,类似于

do_some_arithmetic_in_unsigned_mode(int some_signed_value) { unsigned int magnitude; int negative; if(some_signed_value<0) { magnitude = 0 - some_signed_value; negative = 1; } else { magnitude = some_signed_value; negative = 0; } ...snip... } 

但是INT_MIN可能有问题,0 – 如果在带符号算术中执行,INT_MIN是UB。 在C中执行此操作的标准/健壮/安全/有效方法是什么?

编辑:

如果我们知道我们是2补码,那么隐式转换和显式位操作可能是标准的吗? 如果可能的话,我想避免这种假设。

 do_some_arithmetic_in_unsigned_mode(int some_signed_value) { unsigned int magnitude=some_signed_value; int negative=some_signed_value<0; if (negative) { magnitude = (~magnitude) + 1; } ...snip... } 

从有符号到无符号的转换是明确定义的:您获得相应的代表模2 N. 因此,以下将给出n的正确绝对值:

 int n = /* ... */; unsigned int abs_n = n < 0 ? UINT_MAX - ((unsigned int)(n)) + 1U : (unsigned int)(n); 

更新:正如@ aka.nice建议的那样,我们实际上可以用UINT_MAX + 1U代替UINT_MAX + 1U

 unsigned int abs_n = n < 0 : -((unsigned int)(n)) : (unsigned int)(n); 

在否定的情况下,取some_signed_value+1 。 否定它(这是安全的,因为它不能是INT_MIN )。 转换为无符号。 然后加一个;

您始终可以测试>= -INT_MAX ,这始终是定义良好的。 唯一令人感兴趣的是INT_MIN < -INT_MAXsome_signed_value == INT_MIN 。 您必须单独测试该案例。

  static unsigned absolute(int x) { if (INT_MIN == x) { /* Avoid tricky arithmetic overflow possibilities */ return ((unsigned) -(INT_MIN + 1)) + 1U; } else if (x < 0) { return -x; } else { return x; } }