Manière correcte de prendre la valeur absolue de INT_MIN

Je veux effectuer des calculs arithmétiques non signés, et je dois prendre la valeur absolue de int négatif, comme

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

Mais INT_MIN peut être problématique, 0 – INT_MIN est UB s’il est exécuté en arithmétique signée. Qu’est-ce qu’un moyen standard / robuste / sûr / efficace de le faire en C?

MODIFIER:

Si nous soaps que nous sums en complément à 2, peut-être que la conversion implicite et les opérations sur bits explicites seraient standard si possible, j’aimerais éviter cette hypothèse.

 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 conversion de signé en non signé est bien définie: vous obtenez le représentant correspondant modulo 2 N. Par conséquent, ce qui suit vous donnera la valeur absolue correcte de n :

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

Mise à jour: Comme @ aka.nice le suggère, nous pouvons remplacer UINT_MAX + 1U par 0U :

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

Dans le cas négatif, prenez some_signed_value+1 . Annulez-le (c’est sûr car cela ne peut pas être INT_MIN ). Convertir en non signé. Puis en append un;

Vous pouvez toujours tester >= -INT_MAX , cela est toujours bien défini. Le seul cas qui soit intéressant pour vous est si INT_MIN < -INT_MAX et que some_signed_value == INT_MIN . Vous devrez tester ce cas séparément.

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