Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2962 connectés 

  FORUM HardWare.fr
  Programmation
  C

  Conversions arithmétiques

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Conversions arithmétiques

n°1422789
Gattuso
Posté le 09-08-2006 à 12:27:27  profilanswer
 

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
mood
Publicité
Posté le 09-08-2006 à 12:27:27  profilanswer
 

n°1422820
olivthill
Posté le 09-08-2006 à 13:27:35  profilanswer
 

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.

n°1422821
skelter
Posté le 09-08-2006 à 13:28:17  profilanswer
 

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
n°1422824
skelter
Posté le 09-08-2006 à 13:30:35  profilanswer
 

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

n°1422831
pains-aux-​raisins
Fatal error
Posté le 09-08-2006 à 13:37:47  profilanswer
 

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

n°1422834
Elmoricq
Modérateur
Posté le 09-08-2006 à 13:44:08  profilanswer
 

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.

n°1422841
skelter
Posté le 09-08-2006 à 13:48:28  profilanswer
 

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

n°1422844
pains-aux-​raisins
Fatal error
Posté le 09-08-2006 à 13:51:08  profilanswer
 

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.

n°1422847
skelter
Posté le 09-08-2006 à 13:53:30  profilanswer
 

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

n°1422851
pains-aux-​raisins
Fatal error
Posté le 09-08-2006 à 13:56:52  profilanswer
 

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

mood
Publicité
Posté le 09-08-2006 à 13:56:52  profilanswer
 

n°1422856
skelter
Posté le 09-08-2006 à 14:01:32  profilanswer
 

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 ?

n°1422857
pains-aux-​raisins
Fatal error
Posté le 09-08-2006 à 14:05:19  profilanswer
 

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
n°1422860
skelter
Posté le 09-08-2006 à 14:11:11  profilanswer
 

oui ok, entre signed-unsigned il n'y a rien de définie par la norme

n°1422862
_darkalt3_
Proctopathe
Posté le 09-08-2006 à 14:12:25  profilanswer
 

[:drapal]


---------------
Töp of the plöp
n°1422926
Taz
bisounours-codeur
Posté le 09-08-2006 à 15:17:14  profilanswer
 

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
n°1423580
db__
spécialiste de l'à peu près
Posté le 10-08-2006 à 12:43:21  profilanswer
 

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.

n°1425207
Taz
bisounours-codeur
Posté le 14-08-2006 à 10:07:27  profilanswer
 

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.

n°1436210
db__
spécialiste de l'à peu près
Posté le 04-09-2006 à 13:01:55  profilanswer
 

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

n°1436460
Emmanuel D​elahaye
C is a sharp tool
Posté le 04-09-2006 à 21:33:13  profilanswer
 

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/
n°1436492
Sve@r
Posté le 04-09-2006 à 22:45:55  profilanswer
 

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
n°1436692
db__
spécialiste de l'à peu près
Posté le 05-09-2006 à 12:38:17  profilanswer
 

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 ?

n°1436751
Sve@r
Posté le 05-09-2006 à 13:59:49  profilanswer
 

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.
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  Conversions arithmétiques

 

Sujets relatifs
opérations arithmétiques[VB.NET] Conversions de données ...
Conversions utilisateur[C++] Conversions
Stringstreams & conversions strings -> types numériques[MySQL] SELECT CONCAT et fonctions arithmétiques
Plus de sujets relatifs à : Conversions arithmétiques


Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)