Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

integer overflow différence entre entiers signés et non signés

4 réponses
Avatar
Taurre
Bonjour =E0 tous,

Dans le cas d'un d=E9passement d'entier, la norme C op=E8re une diff=E9renc=
e entre les entiers sign=E9s et non sign=E9s. En effet, dans le premier cas=
, le comportement est ind=E9termin=E9 alors que dans le second il y aura =
=AB wrap around =BB (C11 [n1570] =A7 6.2.5 al 9 p 40). J'aurais voulu conna=
=EEtre l'origine d'une telle distinction ?=20

Aussi, comment celle-ci se mat=E9rialise-t-elle sur certaines architectures=
? Je veux dire, sur un processeur x86 ou x86_64, il y a un =AB wrap around=
=BB dans les deux cas et il n'y a aucune v=E9rification de la part du proc=
esseur (il y a un juste un drapeau qui est lev=E9 s'il y a d=E9passement de=
la capacit=E9 d'un registre me semble-t-il). Je me demande donc comment un=
e architecture ferait pour distinguer une arithm=E9tique sign=E9e d'une ari=
thm=E9tique non sign=E9 afin d'avoir un comportement diff=E9rent suivant le=
cas (je ne sais pas si je suis clair) ?

Merci d'avance pour vos r=E9ponses.

4 réponses

Avatar
Jean-Marc Bourguet
Taurre writes:

Dans le cas d'un dépassement d'entier, la norme C opère une différence
entre les entiers signés et non signés. En effet, dans le premier cas, le
comportement est indéterminé alors que dans le second il y aura « wrap
around » (C11 [n1570] § 6.2.5 al 9 p 40). J'aurais voulu connaître
l'origine d'une telle distinction ?



S'il y a peut-être eu des machines ne proposant pas d'opérations sur les
entiers non-signés, celles qui en ont n'ont pas de variations sur leur
effet. Tandis qu'il y a des variations sur le comportement des opérations
sur les signés et la norme C cherche à permettre l'implémentation la plus
naturelle pour l'architecture plutôt qu'à favoriser la portabilité.

Aussi, comment celle-ci se matérialise-t-elle sur certaines architectures ?
Je veux dire, sur un processeur x86 ou x86_64, il y a un « wrap around »
dans les deux cas et il n'y a aucune vérification de la part du processeur
(il y a un juste un drapeau qui est levé s'il y a dépassement de la
capacité d'un registre me semble-t-il). Je me demande donc comment une
architecture ferait pour distinguer une arithmétique signée d'une
arithmétique non signé afin d'avoir un comportement différent suivant le
cas (je ne sais pas si je suis clair) ?



Si dans le cas d'une représentation des entiers en complément à 2, on peut
avoir une seule instruction d'addition capable de traiter à la fois des
entiers signés et non signés (à part les flags, et ce n'est pas toujours le
cas, MIPS -- processeur pourtant conçu avec une approche minimaliste s'il
en est -- a une instruction ADD qui a une interruption en cas d'overflow et
une instruction ADDU), dans le cas des autres représentations prévues par
la norme (complément aux uns et grandeur et signe), ce n'est pas possible,
il faut nécessairement deux instructions (ou en grandeur et signe, avoir
une instruction d'addition qui ne change pas le signe en cas d'overflow
mais fait un wrap around sur la valeur absolue et ne pas utiliser le bit de
signe comme bit de valeur pour les non signés). Dans ces représentation, le
comportement en cas d'overflow a plus de chance d'être une interruption et
il est fortement improbable d'il soit un wrap around aussi simple que celui
du complément à 2.

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Taurre
Voilà qui répond parfaitement à ma question, merci beaucoup :)
Avatar
Antoine Leca
Taurre écrivit :
Dans le cas d'un dépassement d'entier, la norme C opère une différence
entre les entiers signés et non signés. [...]
Aussi, comment celle-ci se matérialise-t-elle sur certaines architectures ?
Je veux dire, sur un processeur x86 ou x86_64, il y a un « wrap around »
dans les deux cas



Pas forcément. Par exemple, avec les jeux d'instructions SSE etc. to
peux implémenter les opérations en utilisant les opérations vectorisées;
et dans ce cadre-là, tu pourrais utiliser l’addition bornée (si le
résultat mathématique dépasse xINT_MAX, le registre reste figé à
xINT_MAX au lieu de contenir une valeur négative).

La seule chose que dis la norme dans ce cas-là, c'est qu'on ne peut pas
présupposer le comportement ; autrement dit que le programme ne *doit*
pas compter sur le fait que l'implémentation utilise un débordement ou
une arithmétique bornée, parfois d'une expression à l'autre ou même
d'une occurrence de boucle à la suivante (ce qui est parfaitement
plausible si l'implémentation déroule la boucle.)


Antoine
Avatar
Taurre
Aah ! Je n'aurais pas pensé à la possibilité d'utiliser les
instructions SSE en lieu et place des instructions basiques. Merci
pour la précision :)