Division de nombre entiers signés par non signés
Le
Yann Renard
Bonjour à tous,
avec le code suivant, je m'attends à obtenir "-1" comme résultat.
#include <stdio.h>
int main(int argc, char** argv)
{
unsigned long long b = 5;
signed long long a = -5;
signed long long c = a / b;
printf("%lli", c);
return 0;
}
Or j'obtiens 3689348814741910322. La plateforme que j'utilise pour faire
ce test est Ubuntu Linux Lucid Lynx sur architecture x86_64.
# uname -a
Linux cervelet 2.6.32-25-generic #44-Ubuntu SMP Fri Sep 17 20:05:27 UTC
2010 x86_64 GNU/Linux
# gcc --version
gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Compilé sans optimisation. Est ce que je me trompe ? Ou est ce GCC qui
fait des bétises ?
Merci d'avance,
Yann
avec le code suivant, je m'attends à obtenir "-1" comme résultat.
#include <stdio.h>
int main(int argc, char** argv)
{
unsigned long long b = 5;
signed long long a = -5;
signed long long c = a / b;
printf("%lli", c);
return 0;
}
Or j'obtiens 3689348814741910322. La plateforme que j'utilise pour faire
ce test est Ubuntu Linux Lucid Lynx sur architecture x86_64.
# uname -a
Linux cervelet 2.6.32-25-generic #44-Ubuntu SMP Fri Sep 17 20:05:27 UTC
2010 x86_64 GNU/Linux
# gcc --version
gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Compilé sans optimisation. Est ce que je me trompe ? Ou est ce GCC qui
fait des bétises ?
Merci d'avance,
Yann

Poser une question


Et non. Tu as une opération qui implique un signé et un non signé
de même taille. Il faut donc faire une conversion, soit du signé en
non signé, soit du non signé en signé.
La norme dit que c'est le signé qui sera convertit en non signé
(donc surement 2^64 - 6 dans ton cas). Puis on divise par 5.
Puis on convertit le non signé en signé (ce qui se faite sans modif
de la valeur).
gcc a surement plein de bugs, mais sans optimisation, sur une
architecture répandue et sur un code si simple, je pense qu'on
peut lui faire confiance.
Marc Boyer
--
En prenant aux 10% des francais les plus riches 12% de leurs revenus,
on pourrait doubler les revenus des 10% les plus pauvres.
http://www.inegalites.fr/spip.php?a...amp;id_mot0
Merci Marc pour cette réponse rapide.
J'aurais parié que le signé l'aurais emporté sur le non signé ;)
Bonne journée,
Yann
Ce choix de privilégier non signé sur signé m'a beaucoup interrogé.
Il a l'avantage de produire le débordement sur de petites valeurs
négatives, que l'on voit vite sur des tests unitaires, alors que
le choix contraire ne l'aurait fait apparaître sur de grandes valeurs,
que pas grand monde ne teste (jusqu'au jour où la fusée explose ;-) ).
Il a l'inconvénient de faire planter plein de code qui de toutes
façons ne manipuleront jamais de grandes valeurs (genre du nombre
de trimestres de cotisation d'un salarié ;-) ).
Mais un grand ancien va bien passer par là nous expliquer les enjeux
et l'histoire de ce choix.
Marc Boyer
--
En prenant aux 10% des francais les plus riches 12% de leurs revenus,
on pourrait doubler les revenus des 10% les plus pauvres.
http://www.inegalites.fr/spip.php?a...amp;id_mot0
Il y a d'abord un choix de privilegier la valeur (autrement dit si le type
signe est capable de representer toutes les valeurs du type non signe,
c'est le type signe qui est utilise).
Ensuite, quand il n'y a pas un type capable de representer tout
l'intervalle possible de l'autre, utiliser le type non signe a l'avantage
d'etre toujours bien defini (plutot que defini par l'implementation ou non
specifie ou indefini, je ne sais plus -- je crains l'indefini a cause des
traps values).
A+
--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Ceci fait le résultat escompté :
#include
int main (int argc, char **argv)
{
long long b = 5;
long long a = -5;
long long c = a / b;
printf ("%lldn", c);
return 0;
}
Il ne faut pas mélanger les signés et les non signés.