Types entiers

Nous connaissons déjà le type int, qui désigne un entier avec signe codé (sur PC) sur deux octets (seize bits, dont un de signe); son ensemble de valeurs varie donc de -215 à 215-1, c’est-à-dire de -32 768 à 32 767. Il arrive parfois que ces quantités soient insuffisantes. On dispose alors du type « entier long » long int, codé sur quatre octets. Son ensemble de valeurs varie donc de -231 = -2 147 483 648 à 231-1 = 2 147 483 647.

Il existe en outre un type « entier court » short int, mais son ensemble de valeurs est le même que int sur PC. Il n’est donné que pour des raisons de compatibilité avec les systèmes UNIX, sur lesquels les tailles de codage des entiers ne sont pas, en général, les mêmes. On prendra garde en général d’éviter de faire des hypothèses sur les valeurs maximales et minimales des types entiers, qui peuvent varier d’une machine à l’autre, parfois d’un compilateur à l’autre. Pour ppalier ces inconvénients, il est parfoi utile d'utiliser une instruction typedef pour créer un nom de type que l'on ajustera selon les circonstances. Il est possible aussi de calculer le nombre d'octets occupés par un type, en utilisant l'opérateur sizeof.

Chacun de ces trois types peut être utilisé en version sans signe. On obtient alors les types unsigned int, dont les valeurs sont de 0 à 216-1 = 65535, ainsi que unsigned short int, et unsigned long int qui varie de 0 à 232-1 = 4 294 967 295. On peut aussi écrire signed int, etc., mais c’est sans intérêt en général puisque c’est la valeur par défaut.

En pratique, il est assez lourd d’écrire unsigned int par exemple. Il est donc permis d’omettre le mot int dans ces écritures (sauf quand il est seul). On écrira donc unsigned pour unsigned int, long pour long int, et unsigned long pour unsigned long int :

unsigned u, v; long l1, l2;int i, j, k = 0;unsigned long ll = -1; // attention ! valeur 0xFFFFFFFF en fait

Dans cet exemple, on a déclaré deux unsigned int, deux long int, trois int, dont un initialisé à 0, et un unsigned long int initialisé... à une valeur qui ne fait pas partie de son ensemble de valeurs ! Cette écriture est cependant permise.

En effet, lorsque dans un programme un débordement quelconque se produit dans un calcul sur des entiers, aucune erreur n’est signalée. Les calculs se poursuivent simplement en tronquant les bits excédentaires. Il en résulte que les calculs sur les entiers à deux octets (int et short, signés ou non) se font modulo 216 = 65536, et sur les entiers à quatre octets (long et unsigned long) modulo 232 = 4 294 967 296. En conséquence, la variable ll ci-dessus est en fait initialisée à 4 294 967 296 -1 = 4 294 967 295, (ou 0xFFFFFFFF en hexadécimal), soit la plus grande valeur possible pour un unsigned long.

Par ailleurs, lorsque une opération est effectué sur deux types entiers, celle-ci est réalisée avec les arrondis correspondants au plus grand de ces types, indépendamment du type résultat. Par exemple les instructions suivantes:

short i = 256; int j = 512;long l = i*j; // attention !

fournissent la valeur 0 (supposant toujours que int contient deux octets), parce que le produit est effectué dans le type int. Pour contourner ce problème , il faut d'abord convertir l'un des entiers en long, en écrivant par exemple l = i* (long)j. Voir aussi plus loin sur ce point délicat.

Exercice 2.1

Après les initialisations suivantes, combien vaut x ?

int u = 10000, v = 10000;unsigned long x = u *v;
Voir solution
Précédent Précédent Sommaire Sommaire Suivant Suivant