Conversions arithmétiques

Conversions arithmétiques - C - Programmation

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 :

Code :
  1. long int li = 1L;
  2. unsigned int ui = 1U;


Quel est le type de li + ui ?

Message cité 1 fois
Message édité par Gattuso le 09-08-2006 à 12:27:44
Reply

Marsh Posté le 09-08-2006 à 12:27:27   

Reply

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.

Reply

Marsh Posté le 09-08-2006 à 13:28:17    

unsigned long [edit] en fait je dirais plutot long
 
tu peux ecrire

Code :
  1. long int li = 1;
  2. unsigned int ui = 1;


 
c'est equivalent


Message édité par skelter le 09-08-2006 à 13:49:47
Reply

Marsh Posté le 09-08-2006 à 13:30:35    

olivthill a écrit :


La règle veut que cela dépende de la variable de destination, qui n'est pas réprésentée dans la question.


 
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

Reply

Marsh Posté le 09-08-2006 à 13:37:47    

[:drapal]
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.

Reply

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.  
[:klem3i1]
 
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.

Reply

Marsh Posté le 09-08-2006 à 13:48:28    

pains-aux-raisins a écrit :

[:drapal]
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.


 
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

Reply

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.

Reply

Marsh Posté le 09-08-2006 à 13:53:30    

pains-aux-raisins a écrit :


Cependant, il me semble que signed = unsigned en terme de taille mémoire. La plage de valeur des signed étant plus réduite.


 
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

Reply

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à ?

Reply

Marsh Posté le 09-08-2006 à 13:56:52   

Reply

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 ?

Reply

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.


Message édité par pains-aux-raisins le 09-08-2006 à 14:06:19
Reply

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

Reply

Marsh Posté le 09-08-2006 à 14:12:25    

[:drapal]


---------------
Töp of the plöp
Reply

Marsh Posté le 09-08-2006 à 15:17:14    

olivthill a écrit :


La règle veut que cela dépende de la variable de destination, qui n'est pas réprésentée dans la question..


 
Faux.
 
Voir K&R A.6.1 - A.6.5


Message édité par Taz le 09-08-2006 à 15:23:13
Reply

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 :
  1. #include <stdio.h>
  2. int main (int argc, char **argv)
  3. {
  4. int  a, b;
  5. unsigned c, d;
  6. a = -10;
  7. c = 7;
  8. b = a + c;
  9. d = a + c;
  10. printf ("a : %d %u c : %d %u\n", a, a, c, c);
  11. printf ("b : %d %u d : %d %u\n", b, b, d, d);
  12. a = 10;
  13. c = 4294967286;
  14. b = a + c;
  15. d = a + c;
  16. printf ("a : %d %u c : %d %u\n", a, a, c, c);
  17. printf ("b : %d %u d : %d %u\n", b, b, d, d);
  18. return 0;
  19. }


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.

Reply

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.

Reply

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é ?

Reply

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


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 04-09-2006 à 22:45:55    

Gattuso a écrit :

Code :
  1. long int li = 1L;
  2. unsigned int ui = 1U;


Quel est le type de li + ui ?


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 :
 
double c;
int b = 2;
c = 3 / b;
 
Le résultat donne 1 au lieu de 1,5 (si je me souviens bien).


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


Message édité par Sve@r le 04-09-2006 à 22:50:45
Reply

Marsh Posté le 05-09-2006 à 12:38:17    

Bonjour

Citation :

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


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 ?

Reply

Marsh Posté le 05-09-2006 à 13:59:49    

db__ a écrit :

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 ?


Ben le typage n'est pas garanti. Tu peux te retrouver avec ta constante de type "unsigned" comme "signed"...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed