Les types et leur taille
Ce que ce chapitre apporte 5 points
- Donner la taille de chaque type de base, et la lire avec sizeof.
- Prévoir ce que devient un entier qui dépasse sa capacité.
- Distinguer la division entière de la division réelle, et choisir celle qu'on veut.
- Traiter un caractère pour ce qu'il est : un petit entier.
- Prévoir ce que perd une valeur qui passe d'un type à un autre.
En Python, un entier n'a pas de limite : il grandit tant que la mémoire suit, et 2 ** 200 s'écrit comme n'importe quel calcul. C'est commode, et c'est une illusion entretenue à grands frais par l'interpréteur.
En C, un entier occupe quatre octets, ni plus ni moins. Ces quatre octets portent un peu plus de quatre milliards de valeurs distinctes, et quand un calcul sort de cet intervalle, le résultat ne devient pas faux avec un message : il devient faux en silence, et souvent négatif. Ce chapitre montre où sont les bords, ce qui se passe quand on les franchit, et pourquoi diviser deux entiers ne donne pas ce qu'on attend.
Ce que sizeof révèle
sizeof rend le nombre d'octets qu'occupe un type. C'est un des rares opérateurs du langage qui
donne une réponse sur la machine plutôt que sur le calcul.
C'est précisément pour cela que
sizeof existe. Écrire 4 à la place de sizeof(int) dans un programme revient à parier sur la machine qui l'exécutera, et ce pari finit par se perdre.
Que vaut sizeof(int) sur une machine ordinaire ?
Ce qui arrive au bord
Un int signé de quatre octets porte les valeurs de à , soit de
à . Ajouter un au plus grand ne donne pas le suivant.
Le compteur repart du plus petit, comme un compteur kilométrique qui repasse à zéro. Les bits de poids fort qui ne tiennent plus sont simplement perdus, et le bit qui porte le signe se retrouve allumé.
grand + 1 par grand * 2, puis par grand + 2, et relire chaque fois le résultat. Le débordement n'est pas un cas particulier de l'addition de un : c'est ce qui arrive à toute opération dont le résultat ne tient plus.Changer ensuite
char petit = 127 en char petit = 200 : la valeur stockée n'est déjà plus celle qui était écrite, parce qu'un char signé s'arrête à 127.
La parade ne consiste pas à surveiller le résultat après coup, puisqu'il est déjà faux. Elle consiste à choisir un type assez large dès le départ, ou à vérifier avant l'opération que le résultat tiendra.
Diviser deux entiers
En C, l'opération dépend du type des opérandes, pas du résultat attendu.
La dernière ligne est la faute la plus fréquente du langage. La division est calculée entre deux
entiers, donc elle donne 3, et ce 3 est ensuite rangé dans un double qui affiche fidèlement
3.00. Le type de la variable qui reçoit n'a aucune influence sur le calcul qui la remplit.
La règle à garder. Si les deux opérandes sont entiers, l'opération est entière, et le résultat est tronqué vers zéro.
Pour obtenir une division réelle, il faut qu'au moins un des deux opérandes soit réel : écrire 2.0 plutôt que 2, ou multiplier d'abord par 1.0.
Un caractère est un nombre
Le type char ne contient pas de lettre : il contient un entier sur un octet, et l'affichage avec
%c l'interprète comme le code d'un caractère.
La dernière ligne est la conversion que tout programme C finit par écrire : les codes des dix
chiffres se suivent, donc retrancher le code de '0' donne la valeur du chiffre. Aucune fonction
n'est nécessaire, et c'est bien une soustraction d'entiers.
Que vaut l'expression 9 / 2 en C, si 9 et 2 sont des int ?
Ce que perd une conversion
Ranger une valeur dans un type plus étroit ne provoque aucune erreur, et perd ce qui ne tient pas.
La première conversion tronque, elle n'arrondit pas : 19,99 devient 19, et 19,99 euros deviennent 19 euros. La seconde garde le dernier octet de 300, c'est-à-dire 44, et le nombre affiché n'a plus aucun rapport avec celui qui était écrit.
1.Que se passe-t-il quand un int dépasse sa plus grande valeur ?
2.Pourquoi double moyenne = 7 / 2; affiche-t-il 3.00 ?
Mettre en pratique
Le bord d'un type se calcule avant d'être rencontré.
Les bords, les restes et les conversions
- 1.
Quelle est la plus grande valeur d'un int signé de 4 octets ?
- 2.
Quelle est la plus grande valeur d'un char signé de 1 octet ?
- 3.
Combien vaut la division entière 17 / 5 en C ?
- 4.
Combien vaut 17 % 5 ?
- 5.
Le caractère 'A' vaut 65. Combien vaut le caractère 'E' ?
- 6.
Une valeur 300 rangée dans un char signé : quelle valeur reste-t-il ?
- 7.
Un compteur de millisecondes sur un int signé déborde au bout de combien de jours ?
Le dernier résultat est une date célèbre : un système qui compte ses millisecondes dans un int
signé se détraque au bout de vingt-cinq jours environ, ce qui est bien assez long pour que personne
ne s'en aperçoive avant la mise en service.
Que vaut l'expression '7' - '0' ?
Le même programme, compilé pour une carte Arduino Uno, rend sizeof(int) égal à 2 et non à 4. Un int y plafonne donc à 32 767, et un compteur de millisecondes déclaré int déborde au bout d'une trentaine de secondes. C'est la démonstration la plus concrète de ce que ce chapitre établit : la taille d'un type n'appartient pas au langage mais à la machine, et seul sizeof la dit.
Pourquoi écrire sizeof(int) plutôt que 4 dans un programme ?
Parce que 4 est une réponse vraie sur la machine où le programme a été écrit, et une supposition
partout ailleurs. Un int fait deux octets sur certains microcontrôleurs, et un pointeur en fait
huit sur toute machine 64 bits.
Un programme qui réserve n * sizeof(int) octets réserve toujours ce qu'il faut. Un programme qui
réserve n * 4 réserve la moitié de ce qu'il faut le jour où il est recompilé ailleurs, et il
écrase la mémoire qui suit.
Comment calculer une moyenne correcte à partir d'un total et d'un nombre, tous deux entiers ?
En rendant réel au moins un des deux opérandes de la division :
double moyenne = total / (double) nombre;
ou, sans écriture de conversion, en multipliant d'abord par 1.0 :
double moyenne = 1.0 * total / nombre;
Ce qui ne marche pas, c'est de déclarer la variable de réception en double : la division a déjà eu
lieu, entre entiers, et le résultat tronqué est arrivé avant que le type de la variable n'ait son
mot à dire.
Un capteur rend des valeurs entre 0 et 1000, et le programme les accumule dans un int. Au bout de combien de mesures un débordement devient-il possible ?
Dans le pire des cas, chaque mesure vaut 1000. Le total dépasse quand le nombre de mesures dépasse , soit environ 2,1 millions de mesures.
À une mesure par seconde, cela laisse vingt-quatre jours. À cent mesures par seconde, cinq heures et
demie. Le calcul se fait avant d'écrire le programme, et il décide du type : un long long, ou une
moyenne glissante qui ne cumule jamais.
Chapitre révisé en octobre 2026 · Une erreur dans ce chapitre ?
Dans la bibliothèque d'exercices
Les bords d'un int, la division entière, le caractère qui est un nombre, et la conversion qui tronque.
Tous les exercices sur les types et leur taille