Manera correcta de tomar el valor absoluto de INT_MIN

Quiero realizar algo de aritmética en unsigned, y necesito tomar el valor absoluto de int negativo, algo así como

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... } 

Pero INT_MIN puede ser problemático, 0 – INT_MIN es UB si se realiza en aritmética firmada. ¿Qué es una forma estándar / robusta / segura / eficiente de hacer esto en C?

EDITAR:

Si sabemos que estamos en 2 complementos, ¿quizás la conversión implícita y las operaciones de bits explícitas sean estándar? Si es posible, me gustaría evitar este supuesto.

 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... } 

La conversión de firmado a unsigned está bien definida: se obtiene el correspondiente módulo 2 N. Por lo tanto, lo siguiente le dará el valor absoluto correcto de n :

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

Actualización: como @ aka.nice sugiere, podemos reemplazar UINT_MAX + 1U por 0U :

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

En el caso negativo, tome some_signed_value+1 . Negarlo (esto es seguro porque no puede ser INT_MIN ). Convertir a sin firmar. Luego agrega uno;

Siempre puedes probar para >= -INT_MAX , esto siempre está bien definido. El único caso que le interesa es si INT_MIN < -INT_MAX y ese some_signed_value == INT_MIN . Tendrías que probar ese caso por separado.

  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; } }