Conversions arithmétiques - C - Programmation
Marsh Posté le 09-08-2006 à 13:27:35
Un schéma ? Il me semble qu'en français, un schéma est un dessin.
Donc c'est sans doute plutôt une règle qu'il faut donner.
La règle veut que cela dépende de la variable de destination, qui n'est pas réprésentée dans la question.
long int li = 1L;
unsigned int ui = 1U;
long int r1;
unsigned int r2;
r1 = li + ui;
r2 = li + ui;
r1 sera de type long int, alors que r2 sera de type unsigned int.
Peut-être que la question concerne les arrondis et troncations éventuels dans les calculs intermédiaires.
Pour ne pas avoir de problème, le mieux est de toujours utiliser un opérateur de coercition (casting), quand le type n'est pas le même que les autres types :
r2 = (unsigned int)(li) + ui;
En pratique, pour int et unsigned int, je n'ai jamais eu de problème. Mais j'en ai eu pour les divisions entre les int et les doubles. Par exemple :
double c;
int b = 2;
c = 3 / b;
Le résultat donne 1 au lieu de 1,5 (si je me souviens bien).
Pour ce genre de question, le plus simple, au lieu de lire un manuel ou de demander à son voisin, est de faire un petit test soit-même. Les compilations de nos jours sont rapides.
Marsh Posté le 09-08-2006 à 13:28:17
unsigned long [edit] en fait je dirais plutot long
tu peux ecrire
Code :
|
c'est equivalent
Marsh Posté le 09-08-2006 à 13:30:35
olivthill a écrit : |
qui parles de variable de destination ? la question c'est quel est le type de l'expression 'li + ui'
sinon bien sur au final c'est converti vers le type de la variable de destination, c'est une evidence vu que le typage est statique
Marsh Posté le 09-08-2006 à 13:37:47
Je suis pas sûr que ce soit normalisé ISO ce comportement. Autrement dit, il y a des chances pour que ce soit compilo-dependant.
J'aurais tendance à dire que
[long int] + [unsigned int] = [unsigned int]
En supposant que le compilateur cast vers le type le moins précis.
Marsh Posté le 09-08-2006 à 13:44:08
Euh, ouais ok, admettons, mais si on en vient à se poser la question, alors on cast et on cherche pas cent-sept ans Le Bon Comportement(c), surtout si ça peut éviter à celui qui relit le code derrière de se poser la question.
Bref, pour moi c'est une fausse question, surtout que ce genre de cas ne se produit normalement que rarement, si on a bien conçu les choses.
Marsh Posté le 09-08-2006 à 13:48:28
pains-aux-raisins a écrit :
|
le type le plus large entre long et int est long (iso dit int <= long), par contre entre signed et unsigned c'est dependent de l'implementation
Marsh Posté le 09-08-2006 à 13:51:08
skelter > je savais déjà pour char <= int <= long.
Cependant, il me semble que signed = unsigned en terme de taille mémoire. La plage de valeur des signed étant plus réduite.
Marsh Posté le 09-08-2006 à 13:53:30
pains-aux-raisins a écrit : |
oui, j'ai vu que ca dépend
qu'est ce que tu entends par "plage de valeur des signed étant plus réduite" ? ca aussi ca dépend, en complément à 2 on code autant de valeur
Marsh Posté le 09-08-2006 à 13:56:52
entre un signed et un unsigned, même en complément à 2 on ne peut pas coder autant de valeur.
Que veux-tu dire par là ?
Marsh Posté le 09-08-2006 à 14:01:32
sur un entier N bits non signé on code 2^N valeurs
en signé on code 2^(N-1) + (2^(N-1) + 1) -> 2^N en complément à 2, non ?
Marsh Posté le 09-08-2006 à 14:05:19
ah, je me suis mal exprimé
edit : par exemple...
unsigned short : 0..255
signed short : -128..127
Même taille (on est d'accord là dessus) mais max(abs(unsigned)) > max(abs(signed)
Le terme de plage ne convient pas effectivement.
Marsh Posté le 09-08-2006 à 14:11:11
oui ok, entre signed-unsigned il n'y a rien de définie par la norme
Marsh Posté le 09-08-2006 à 15:17:14
olivthill a écrit : |
Faux.
Voir K&R A.6.1 - A.6.5
Marsh Posté le 10-08-2006 à 12:43:21
Bonjour
le sujet étant de rajouter un unsigned a un signed, du point de vue du microprocesseur le résultat sera le même. La différence ne sera qu'une différence d'interprétation du programmeur.
A mon avis, il n'y a aucun compilateur qui signale les erreurs de débordements (OF) et de retenue (CF)
Code :
|
compilation
dominique@saussignac:~/temp$ gcc -Wall -o essai1 essai1.c
essai1.c: In function main:
essai1.c:14: attention : cette constante décimale est « unsigned » seulement en C90 ISO
dominique@saussignac:~/temp$ ./essai1
a : -10 4294967286 c : 7 7
b : -3 4294967293 d : -3 4294967293
a : 10 10 c : -10 4294967286
b : 0 0 d : 0 0
Comme prévu le résultat est le même et tout dépend de la représentation qu'on se fait de la suite de bit que contient une case mémoire.
Si un expert peut éclairer l'avertissement du compilateur ?
Il se peut que le comportement soit différend sur une machine 64 bits.
En assembleur, on peut controler les débordements et éviter des résultats faux. Je ne sait pas si c'est possible en C.
Marsh Posté le 14-08-2006 à 10:07:27
db__ a écrit : du point de vue du microprocesseur le résultat sera le même. |
ce n'est pas qu'une manière d'interpréter. Beaucoup de processeur ont des instructions spécifiques pour les calculs non-signés.
Marsh Posté le 04-09-2006 à 13:01:55
bonjour
Le contexte du sujet est l'addition d'entier.
Il existe effectivement des instructions différentes pour les multiplications et divisions suivant qu'il s'agit d'entiers signés ou non signés. Dans le cas de l'addition et de la soustraction, je ne vois pas l'intéret d'une opération spécifique pour les entiers signés sauf si le processeur ne fait pas de l'arithmétique binaire en complément à 2 ou si le processeur ne gère pas les débordements avec un indicateur spécifique.
Si les nombres sont en décimal codé binaire, il faut une instruction spécifique pour gérer le signe.
Quels sont ces processeurs ?
Que dit la norme C pour les débordements de capacité ?
Marsh Posté le 04-09-2006 à 21:33:13
db__ a écrit : Que dit la norme C pour les débordements de capacité ? |
Si le type est signé : Cà dépend de l'implémentartion
Si le type est non signé, il y a 'retournement' (wrap)
U<type>_MAX + 1 = 0
Marsh Posté le 04-09-2006 à 22:45:55
Gattuso a écrit :
|
Le type de la variable la plus "large" utilisée dans l'expression (ici "long int" )
olivthill a écrit : En pratique, pour int et unsigned int, je n'ai jamais eu de problème. Mais j'en ai eu pour les divisions entre les int et les doubles. Par exemple : |
Tu parles de division entre "int" et "double" mais dans ton exemple, tu divises un "int" par un "int". Il est tout à fait normal que le résultat soit un "int". Que tu mettes ce résultat dans un "double" ne changera rien à sa valeur...
Ecris "c= 3.0 / b" ou bien "c=3 / (double) b" et tu obtiendras la bonne valeur...
Marsh Posté le 05-09-2006 à 12:38:17
Bonjour
Citation : Si le type est signé : Cà dépend de l'implémentartion |
Donc si on a affaire à des nombres proches de la limite de capacité, il faut utiliser des double ou gérer les débordements par l'assembleur.
Citation : essai1.c:14: attention : cette constante décimale est « unsigned » seulement en C90 ISO |
Quelqu'un saurrait-il expliquer cet avertissement peu explicite ?
que ce passe-t-il en C non C90 ISO ?
Marsh Posté le 05-09-2006 à 13:59:49
db__ a écrit :
|
Ben le typage n'est pas garanti. Tu peux te retrouver avec ta constante de type "unsigned" comme "signed"...
Marsh Posté le 09-08-2006 à 12:27:27
Bonjour,
je voudrais savoir s'il existe un schéma permettant de savoir quel type donnera l'addition de 2 types différents.
Par exemple, si j'ai :
Quel est le type de li + ui ?
Message édité par Gattuso le 09-08-2006 à 12:27:44