GNU/Linux >> Tutoriels Linux >  >> Linux

Tutoriel de programmation Linux C Partie 15 - Complément 2s et nombres négatifs

Jusqu'à présent, dans cette série de didacticiels de programmation en C, nous avons discuté de plusieurs concepts, mais nous en avons manqué un de base. Il s'agit de nombres négatifs. Oui, bien que nous ayons brièvement mentionné les variables signées et non signées dans l'un de nos premiers tutoriels, nous n'avons pas vraiment discuté de la façon dont les nombres négatifs sont stockés en mémoire.

Eh bien, c'est exactement ce qui sera discuté dans ce tutoriel. Alors sans plus tarder, commençons la discussion.

complément à 2

Avant de commencer avec l'explication sur la représentation des nombres négatifs en mémoire, il est important que nous connaissions le concept de complément à 1 et à 2, qui sont tous deux des opérations de niveau binaire.

Prenons un exemple très simple. Supposons que vous ayez un entier de 4 octets 'a' avec une valeur décimale de 15. Alors voici comment il est représenté dans la mémoire sous forme binaire :

00000000 00000000 00000000 00001111

Maintenant, pour calculer le complément à un, il suffit d'inverser tous les bits. Voici donc la représentation du complément à 1 de 15 :

11111111 11111111 11111111 11110000

Maintenant, si vous ajoutez 1 à la représentation binaire ci-dessus, vous obtenez le complément à 2.

11111111 11111111 11111111 11110001

La représentation ci-dessus est donc le complément à deux de 15.

Nombres négatifs

Maintenant, certains d'entre vous doivent se demander pourquoi nous avons discuté du complément à 1 et à 2 ? Eh bien, la réponse réside dans le fait que la représentation binaire d'un nombre négatif est calculée par le complément à 2.

Difficile à croire? En voici la preuve :

Le complément à 2 que nous avons calculé dans la section précédente peut être représenté sous forme hexadécimale par 0xFFFFFFF1. Voyons maintenant quelle est cette valeur sous forme décimale via un programme C

Voici le code :

#include <stdio.h>

int main()
{
int a = 0xFFFFFFF1;
printf("a = %d", a);

return 0;
}

Et voici le résultat :

a = -15

Croyez-le maintenant? Nous avons commencé avec un nombre '15', avons calculé son complément à 2, et lorsque nous avons de nouveau converti la valeur du complément à deux en décimal, nous avons trouvé qu'il s'agissait de -15.

Passons à autre chose, maintenant modifions légèrement le code pour nous assurer que l'appel printf lit la valeur de la variable 'a' comme comme un entier non signé.

#include <stdio.h>

int main()
{
int a = 0xFFFFFFF1;
printf("a = %u", a);

return 0;
}

Voici maintenant le résultat :

a = 4294967281

Oups, la sortie a changé, et maintenant c'est une énorme valeur positive. Mais pourquoi c'est arrivé ? 0xFFFFFFF1 n'est-il pas le complément à 2 de 15 comme nous l'avons vu plus tôt ?

Oui, 0xFFFFFFF1 est le complément à deux de 15, mais si vous ne le regardez pas sous cet angle, il s'agit également d'une valeur normale (4294967281). La différence réside dans la façon dont il est lu. S'il est lu comme un entier signé (via %d dans printf), vous verrez la sortie comme -15, mais s'il est lu comme un entier non signé (via %u dans printf), vous verrez la sortie comme 4294967281.

En règle générale avec les variables signées (qui traitent à la fois des valeurs négatives et positives), gardez à l'esprit que la représentation binaire des nombres négatifs a toujours '1' comme bit le plus à gauche, tandis qu'en cas de nombres positifs, le bit en question est toujours 0.  

Enfin, notez que vous pouvez également inverser la représentation d'un complément à deux pour obtenir sa contrepartie positive. À titre d'exemple, prenons à nouveau la valeur 0xFFFFFFF1, qui est la représentation hexadécimale de -15. Il est représenté sous forme binaire comme :

11111111 11111111 11111111 11110001

Maintenant, pour obtenir sa contrepartie positive, il suffit d'effectuer à nouveau un complément à 2. Ce qui signifie, d'abord faire un complément à 1 :

00000000 00000000 00000000 00001110

Et puis ajoutez 1

00000000 00000000 00000000 00001111

Maintenant, si vous convertissez ceci, vous obtiendrez la valeur 15 sous forme décimale.

Conclusion

J'espère que ce tutoriel vous a aidé à comprendre le concept de nombres négatifs dans le contexte de la façon dont ils sont représentés en mémoire. Je vous suggère d'essayer les exemples que nous avons utilisés dans ce tutoriel, et si vous rencontrez un problème, ou si vous avez un doute ou une question, laissez-nous un commentaire ci-dessous.


Linux
  1. Tutoriel de programmation en C 4 - Variables et mémoire

  2. Tutoriel de programmation en C Partie 3 - Notions de base sur les variables

  3. Tutoriel de programmation en C Partie 5 - Variables de caractères

  4. Tutoriel de programmation Linux C Partie 10 - Portées variables

  5. Tutoriel de programmation Linux C Partie 9 :Chaînes

5 trucs et astuces intéressants en ligne de commande sous Linux - Partie 1

Comment comparer et fusionner des fichiers texte sous Linux (partie 2)

Tutoriel sur les commandes Linux nice et renice (7 exemples)

Tutoriel de programmation Linux C Partie 18 :Fonctions récursives

Comment installer et utiliser KompoZer sous Linux - Tutoriel

Le tri Linux ne fonctionne pas avec les nombres flottants négatifs