Voir les cours et résoudre les problèmes en :
Le C est un langage de programmation impératif conçu pour la programmation système. Inventé au début des années 1970 avec UNIX, C est devenu un des langages les plus utilisés. De nombreux langages plus modernes se sont inspirés de sa syntaxe. Il privilégie la performance sur la simplicité de la syntaxe. [En savoir plus]
Le C++ est un langage de programmation impératif. Inventé au début des années 1980, il apporte de nouveaux concepts au langage C (les objets, la généricité), le modernise et lui ajoute de nombreuses bibliothèques. C++ est devenu l'un des langages les plus utilisés. Sa performance et sa richesse en font le langage de prédilection pour les concours. [En savoir plus]
Pascal est un langage de programmation impératif inventé dans les années 1970 dans un but d'enseignement. Quoiqu'encore utilisé à cette fin, l'absence de bibliothèque standard en limite son utilisation malgré une grande efficacité. Sa syntaxe a été reprise par d'autres langages plus modernes avec plus ou moins de succès. [En savoir plus]


Remarque : Les cours pour ce langage ne sont disponibles que jusqu'au chapitre 4, « Lecture de l'entrée ». Les corrections sont toutefois toujours fournies.
OCaml est un langage de programmation fonctionnel inventé au milieu des années 1990. Il permet aussi une programmation impérative ou objet. Il permet d'écrire des programmes courts et faciles à vérifier et est ainsi utilisé pour certains systèmes embarqués très sensibles comme ceux des avions. Il est utilisé dans l'enseignement en classes préparatoires aux grandes écoles. [En savoir plus]


Remarque : Les cours pour ce langage ne sont disponibles que jusqu'au chapitre 4, « Lecture de l'entrée ». Les corrections sont toutefois toujours fournies.
Java est un langage de programmation impératif et orienté objet. Inventé au début des années 1990, il reprend en grande partie la syntaxe du langage C++ tout en la simplifiant, au prix d'une performance un peu moins bonne. S'exécutant dans une machine virtuelle, il assure une grande portabilité et ses très nombreuses bibliothèques en font un langage très utilisé. On lui reproche toutefois la « verbosité » de son code. [En savoir plus]


Remarque : Pour un débutant souhaitant apprendre Java, nous conseillons fortement de commencer par JavaScool, plus facile à apprendre, bien que fortement similaire.
Java's Cool (alias JavaScool) est conçu spécifiquement pour l'apprentissage des bases de la programmation. Il reprend en grande partie la syntaxe de Java sur laquelle il s'appuie, mais la simplifie pour un apprentissage plus aisé. La plateforme JavaScool est accompagnée d'un ensemble d'activités diverses de découverte de la programmation. [En savoir plus]
Python est un langage de programmation impératif inventé à la fin des années 1980. Il permet une programmation orientée objet et admet une syntaxe concise et claire qui en font un langage très bien adapté aux débutants. Étant un langage interprété, il n'est cependant pas aussi performant que d'autres langages. [En savoir plus]
Représentation binaire du type int

Comme nous l'avons vu dans la section précédente, il existe une limite aux valeurs que l'on peut stocker dans une variable. Dans le cas des entiers, cette limite n'est cependant pas toujours la même et dépend de la machine sur laquelle votre programme va s'exécuter.

Les entiers sont stockés sur la machine sous la forme de nombres en base binaire. Il y a cependant une limite sur le nombre de chiffres que l'on peut stocker dans une variable de type int. Cette limite est de 32 chiffres sur les machines récentes, mais peut être de 16 sur d'autres. On considérera pour l'instant que la limite est de 32, puisque c'est très probablement le cas sur la machine que vous utilisez. La mémoire utilisée pour stocker une variable de type int est donc de 32 chiffres binaires, que l'on appelle bits. On dit ainsi que l'on manipule des entiers 32 bits. Cela correspond également à quatre octets, un octet correspondant à huit bits.

Il existe une différence entre la notation binaire que nous avons vue dans la section précédente et le stockage des nombres dans une variable de 32 bits. Cette différence porte sur la manière de stocker les nombres négatifs. En base binaire "classique", on écrit un nombre négatif en base 2 de la même manière qu'en base 10 : en mettant un signe - devant. Le nombre -9 s'écrit ainsi -1001. Or, dans une variable entière sur 32 bits, on dispose de 32 chiffres pour stocker un nombre et de rien d'autre. On doit donc utiliser ces chiffres eux-mêmes pour déterminer si le nombre est négatif ou non.

Pour comprendre comment les nombres négatifs sont stockés, prenons l'exemple d'un compteur kilométrique d'une voiture (suffisamment ancienne pour que ce compteur soit mécanique), composé de 8 chiffres. Lorsque l'on avance de 100m, le chiffre de droite tourne d'un cran, et passe au chiffre suivant. S'il passe de 9 à 0, le chiffre suivant tourne d'un cran également, etc.

Supposons maintenant qu'il soit possible de le faire remonter en arrière. Que se passe-t-il lorsque tous les chiffres sont à 0 et que l'on le fait tourner à l'envers ? Votre compteur aura probablement tous ses chiffres qui repasseront à 9. La valeur "-1" sera alors représentée par l'affichage : 99999999 (tous les chiffres à 9).

Comment déterminer si ce nombre 99999999 représente la valeur -1, ou la très grande valeur positive que nous lisons ? Il n'y a pas de recette miracle : il faut décider une fois pour toutes que les nombres supérieurs à une certaine valeur seront des nombres négatifs. On peut par exemple dire que tous les nombres au dessus de 50000000 doivent être considérés comme négatifs. Le plus grand nombre positif pouvant être représenté est alors 49999999. La valeur 50000000 représente le nombre -50000000, puisque 50000000 + 50000000 = 100000000, soit 00000000 sur notre compteur à 8 chiffres.

Ceci est exactement le principe que l'on applique pour stocker des entiers négatifs dans une variable de 32 bits. La valeur -1 est représentée par le nombre 11111111111111111111111111111111 (32 bits à 1), la valeur -2 par 11111111111111111111111111111110, etc. On définit que les nombres doivent être considérés comme négatifs à partir de la valeur : 10000000000000000000000000000000. Le plus grand entier que l'on peut stocker est alors : 01111111111111111111111111111111 (un zéro, suivi de 31 uns).

Si l'on traduit ces nombres en base 10, on en déduit que la plus grande valeur que l'on peut stocker sur un entier 32 bits est de 231-1, c'est à dire 2147483647 (un peu plus de deux milliards). La valeur la plus petite que l'on puisse stocker est -231, soit -2147483648.

Exercice : on a évoqué le fait que sur certaines machines, une variable de type int est stockée sur 16 bits seulement. Quelles sont à votre avis les valeurs minimales et maximales d'une variable int sur ces machines ?


Solution : En appliquant le même principe, on définit que les nombres négatifs sont les nombres à partir de 1000000000000000 (un 1 suivi de 15 zéros). Le plus grand nombre (positif) est donc 215 - 1 soit 32767, et le plus petit nombre est -215, soit -32768.


Exercice : déterminer un critère simple pour déterminer à partir de sa notation binaire 32 bits, si un nombre est positif ou négatif.


Solution : Les nombres négatifs étant ceux à partir de 10000000000000000000000000000000, il suffit de regarder le premier bit de la valeur. S'il est à 1, c'est un nombre négatif, s'il est à 0, c'est un nombre positif.


Dépassements de capacité

Nous venons de voir qu'il y a une limite aux valeurs que peut prendre un entier. Que se passe-t-il lorsque l'on dépasse cette limite ? Pour le voir, testez le programme suivant et essayez de comprendre le résultat.

#include <stdio.h>

int main()
{
   int grandeValeur = 2147483647;
   printf("Valeur de départ : %d\n", grandeValeur);
   grandeValeur++;
   printf("Après incrémentation : %d\n", grandeValeur);
   grandeValeur--;
   printf("Après décrémentation : %d\n", grandeValeur);
   return 0;
}

Le programme devrait afficher le texte suivant :

Valeur de départ : 2147483647
Après incrémentation : -2147483648
Après décrémentation : 2147483647

La valeur initiale 2147483647 correspond à la plus grande valeur positive que peut contenir une variable int. Elle correspond à la valeur binaire 01111111111111111111111111111111. Si on l'incrémente de 1, on obtient en binaire, 10000000000000000000000000000000, qui est la toute première valeur négative que l'on peut représenter. On a en fait "fait le tour" des valeurs possibles.

On aurait pu "faire le tour" de nombreuses manières différentes. Une multiplication du nombre initial par 5 aurait ainsi donné la valeur 2147483643, après deux dépassements de capacité en une même opération.

La machine ne fait aucune vérification de dépassement de la capacité d'un entier. Lorsque vous écrivez un programme, vous devez donc systématiquement vérifier vous-mêmes que les valeurs que vous manipulez ne risquent pas de dépasser les valeurs maximales qu'un int permet de gérer. Si vous ne le faites pas, vous risquez de rencontrer des erreurs d'exécution difficiles à détecter.

Pensez à vous inscrire pour valider les cours et résoudre les exercices.