Bonjour,
Tout est presque dans le titre. Il y a quelques temps, j'avais codé pour le boulot une petite application pour entrer des nombres en console et les convertir en décimal ou en hexadécimal selon le mode d'entrée. Pas de soucis tant qu'on reste sur des nombres positifs et que 0xF est considéré comme valant 15 et non -1.
Ça s'est très sérieusement corsé quand j'ai voulu passer à des nombres négatifs en compléments à 2. Je voulais que, dans ce cas, 0xF soit interprété comme -1. Pas de soucis pour saisir un nombre négatif et le convertir en hexadécimal si on n'est pas trop exigeant sur le nombre de F rajoutés devant :
La technique que j'ai adopté pour les nombres saisis en hexadécimal est la suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 printf("-1 = %X\n\n", -1); // Sortie : // -1 = FFFFFFFF
- saisie d'une chaine de caractères
- conversion en nombre
- si le nombre doit être interprété comme négatif, alors faire un masque pour "étendre le MSB" et avoir tout plein de F ; s'il est positif, alors aucun traitement à cette étape
- prendre le complément à 2
- afficher le résultat
Globalement, ça marche bien. 0xF est interprété comme -1 ; 0x0F comme 15.
J'ai deux soucis :
- le traitement aux limites, pour détecter les dépassements de format
- la portabilité du masque car il est fait de façon bourrin :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 // Traitement particulier pour les nombres negatifs if( !(str[0]>='0' && str[0]<'8') ) { // Extend MSB switch(strlen(str)) { case(1): number = 0xFFFFFFF0UL | number; break; case(2): number = 0xFFFFFF00UL | number; break; case(3): number = 0xFFFFF000UL | number; break; case(4): number = 0xFFFF0000UL | number; break; case(5): number = 0xFFF00000UL | number; break; case(6): number = 0xFF000000UL | number; break; case(7): number = 0xF0000000UL | number; break; case(8): number = 0x00000000UL | number; break; default: printf("WTF?\n"); number = 0; break; }
Je travaille sous XP en 32 bits, donc un long fait 4 octets. Quand je vais passer sur 64 bits...
Je ne suis pas certain que ma méthode soit la bonne.... Et je viens donc demander vos avis ! Je vous joins un fichier compilable pour les plus motivés d'entre vous : il donne une application console où vous n'avez qu'à taper des nombre en hexa et faire ENTREE. La boucle se termine quand vous entrer 0.
Merci d'avance pour vos remarques
Bktero.
Partager