C: comportement unaire de l’opérateur moins avec des opérandes non signés

Je n’arrive pas à trouver les éléments pertinents dans la norme C définissant complètement le comportement de l’opérateur unaire moins avec des opérandes non signés.

Le standard C ++ 2003 (oui, C ++, avec moi pour quelques lignes) dit en 5.3.1c7: The negative of an unsigned quantity is computed by subtracting its value from 2^n, where n is the number of bits in the promoted operand.

Le standard C de 1999, cependant, n’inclut pas une telle déclaration explicite et ne définit pas clairement le comportement unaire, ni dans 6.5.3.3c1,3 ni dans 6.5c4. Dans ce dernier, Some operators (the unary operator ~, and the binary operators <>, &, ^, and |, ...) ... return values that depend on the internal representations of integers, and have implementation-defined and undefined aspects for signed types.) , ce qui exclut le moins unaire et les choses semblent restr floues.

Cette question précédente fait référence à la section A.7.4.5 du manuel AN & C de K & R ANSI C qui indique que The negative of an unsigned quantity is computed by subtracting the promoted value from the largest value of the promoted type and adding one .

Quel serait le standard C de 1999 équivalent à la citation ci-dessus du livre?

6.2.5c9 dit: A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.

Est-ce que c’est ça? Ou y a-t-il autre chose qui me manque?

Oui, 6.2.5c9 est exactement le paragraphe que vous avez recherché.

Dans chaque implémentation que je connaisse, un négatif correspond à un complément de deux …

 int a = 12; int b = -a; int c = ~a + 1; assert(b == c); 

… donc il n’y a vraiment pas de différence physique entre les entiers non signés négatifs et signés négatifs – la seule différence réside dans la façon dont ils sont interprétés .

Donc, dans cet exemple …

 unsigned a = 12; unsigned b = -a; int c = -a; 

… les b et c vont contenir exactement les mêmes bits. La seule différence est que b est interprété comme 2 ^ 32-12 (ou 2 ^ 64-12), alors que c est interprété comme “normal” -12.

Ainsi, un négatif est calculé exactement de la même manière, quel que soit le “signe”, et la conversion entre non signé et signé est en fait un non-op (et ne peut jamais causer un débordement dans la mesure où certains bits doivent être “coupés”. -de”).

Le comportement de l’opérateur unaire moins sur les opérandes non signés n’a aucun rapport avec le fait qu’une machine utilise l’arithmétique du complément à deux avec des nombres signés. Au lieu de cela, étant donné unsigned int x,y; la déclaration y=-x; fera en sorte que y reçoive la valeur qu’il devrait conserver pour que x+y égal à zéro. Si x est zéro, y sera également zéro. Pour toute autre valeur de x , il s’agira de UINT_MAX-x+1 , auquel cas la valeur arithmétique de x+y sera de UINT_MAX+1+(yy) qui, lorsqu’elle sera affectée à un unsigned integer , sera soustraite de UINT_MAX+1 d’elle, rapportant zéro.