Types de donnée du langage C
Les types de donnée du langage C définissent les caractéristiques de stockage et les opérations disponibles pour chaque valeur et chaque variable d'un code source en langage C. Les types fondamentaux du langage C sont conçus pour pouvoir correspondre aux types supportés par l'architecture de processeur cible. Le langage C possède une vingtaine de types fondamentaux pour représenter des entiers naturels, entiers relatifs et approximations de réels basées sur la représentation en virgule flottante. Le langage offre une syntaxe pour construire des types d'adresse mémoire (pointeurs) vectoriels (tableaux) et composés (comme les structures). En outre, la bibliothèque standard du C fournit des types supplémentaires qui permettent de s'abstraire des types liés aux caractéristiques techniques de l'ordinateur cible.
Types standards
Types principaux
Le langage C fournit quatre spécificateurs arithmétiques de base char, int, float et double ainsi que leurs versions modifiés signed, unsigned, short et long. Le tableau suivant liste les combinaisons et la plage de valeurs minimales pour chaque déclaration[1]. Comme indiqué sur le document cité en référence, ces valeurs sont dépendantes de l'architecture et doivent être remplacées par les valeurs spécifiques à l'architecture sous-jacente.
Type | Explication courte |
---|---|
char | Plus petite unité adressable d'une machine, elle peut contenir les caractères de base. C'est une valeur entière qui peut être signée ou non. |
signed char | Type entier signé capable de représenter au moins les nombres [−127 ; +127]. |
unsigned char | Type entier non-signé capable de représenter au moins les nombres [0 ; 255]. |
short short int signed short signed short int | Type entier signé capable de représenter au moins les nombres [−32767 ; +32767]. |
unsigned short unsigned short int | Type entier non signé capable de représenter au moins les nombres [0 ; 65535]. |
int signed signed int | Type entier standard, signé, capable de représenter au moins les nombres [−32767 ; +32767]. |
unsigned unsigned int | Type entier standard non signé, capable de représenter au moins les nombres [0 ; 65535]. |
long long int signed long signed long int | Type entier signé capable de représenter au moins les nombres [−2147483647 ; +2147483647]. |
unsigned long unsigned long int | Type entier non signé capable de représenter au moins les nombres [0 ; 4294967295]. |
long long long long int signed long long signed long long int | Type entier signé capable de représenter au moins les nombres [−9223372036854775807 ; +9223372036854775807]. |
unsigned long long unsigned long long int | Type entier non signé capable de représenter au moins les nombres [0 ; 18446744073709551615]. |
float | Type flottant de faible précision, 4 octets ou 32 bits sur quasiment tous les systèmes. |
double | Type flottant de précision standard, 8 octets ou 64 bits sur quasiment tous les systèmes. |
long double | Type flottant de précision standard ou étendue. En pratique, selon le système, de la double précision à la quadruple précision. |
Type booléen
C99 (anglais) a ajouté le type booléen _Bool
(vrai / faux). De plus, l'en-tête <stdbool.h>
définit bool
comme un alias pratique pour ce type et fournit également des macros pour true
et false
. _Bool
fonctionne de manière similaire à un type entier normal, à une exception près : toutes les affectations à _Bool
qui ne sont pas 0 (faux) sont stockées comme 1 (vrai). Ce comportement existe pour éviter les dépassements d'entier dans les conversions de rétrécissement implicites. Par exemple, dans le code suivant :
unsigned char b = 256; if (b) { /* faire quelque chose */ }
La variable b
contient false (faux, ou 0) si le caractère unsigned char
a une taille de 8 bits. Cela est dû au fait que la valeur 256 ne correspond pas au type de données, ce qui entraîne l'utilisation des 8 bits inférieurs, donc la valeur est nulle. Cependant, la modification du type fait que le code précédent se comporte normalement :
_Bool b = 256; if (b) { /* faire quelque chose */ }
Le type _Bool garantit aussi que les valeurs vraies soient toujours égales :
_Bool a = 1, b = 2; if (a == b) { /* faire quelque chose */ }
Mesure de la taille
La taille de chaque type dépend du matériel informatique : ainsi, le type int
mesure souvent 4 octets, mais peut mesurer 2 octet sur certains modèles, et 8 sur d'autres. L'opérateur sizeof
donne la taille d'un type par rapport au type char
qui a par définition une taille de 1 :
printf("taille de int : %zu", sizeof(int));
ce qui renvoie par exemple :
taille de int : 4
Généralités
Le langage C a un typage statique : toute variable doit être déclarée avec un type, qui ne peut pas être changé ensuite ; toute constante a un type ; la norme du langage définit pour chaque opérateur quels sont les types admissibles des opérandes, et comment déduire le type du résultat.
Histoire
Dans sa description des origines du langage C, Dennis Ritchie explique que C a été créé pour supporter différents types de donnée[2]. Les ancêtres du langage C, le langage B, et avant BCPL, n'avaient pas de types de données ; ils opéraient sur des mots machine.
Le langage B était conçu pour fonctionner sur un mini-ordinateur PDP-7 qui avait des mots de 18 bits. Ce n'est que l'ordinateur suivant pour lequel le langage B a été conçu, le PDP-11, qui a été capable d'adresser des octets en mémoire. En outre, le fabricant annonçait le futur support de nombres à virgule flottante. Afin de supporter efficacement le traitement des caractères et des nombres flottants, le langage B a été profondément remanié, ce qui a donné le langage C.
Catégories de type de donnée
Type | Catégories | |||
---|---|---|---|---|
_Bool | booléen | entier | arithmétique | scalaire |
enum | énuméré | |||
char | caractère | |||
signed char , short , int , long , long long | entier signé | |||
unsigned char , unsigned short , unsigned int , unsigned long , unsigned long long | entier non signé | |||
float , double , long double | virgule flottante | |||
float _Complex , double _Complex , long double _Complex , float _Imaginary , double _Imaginary , long double _Imaginary | ||||
T* | pointeur | |||
T[] | tableau | agrégé | ||
struct T | structure | |||
union T | union | |||
void | vide |
Les noms des types _Bool
, _Complex
et _Imaginary
commencent par un caractère de soulignement et une majuscule car ils n'ont été normalisés qu'en 1999, et des noms plus naturels auraient pu être incompatibles avec le code existant. Les synonymes bool
, complex
et imaginary
sont définis dans les en-têtes standard <stdbool.h>
et <complex.h>
.
Le type char
peut être signé ou non, selon l'implémentation. Dans tous les cas, il est distinct des types signed char
et unsigned char
.
Les types entiers peuvent être de différentes tailles. La norme garantit que :
1 = sizeof(char)
≤ sizeof(short)
≤ sizeof(int)
≤ sizeof(long)
≤ sizeof(long long)
.
Les types short
, long
et long long
, signés ou non, peuvent optionnellement contenir le mot int
dans leur nom. Par exemple short int
, int long long
, etc.
Les types short
, int
, long
et long long
peuvent optionnellement contenir le mot signed
dans leur nom. Par exemple signed int
.
La norme garantit que la précision du type float
est inférieure ou égale à celle du type double
, qui est inférieure ou égale à celle du type long double
.
Toute valeur scalaire utilisée dans un contexte booléen est considérée comme fausse si sa valeur est nulle, et vraie autrement.
Conversions usuelles de type
Le langage C est faiblement typé dans le sens où il existe de nombreuses conversions automatiques de type.
Promotion des entiers
Le type int
est le type entier par défaut du langage. C'est le type des constantes littérales comme 123
et 'a'
, ainsi que des constantes de listes énumérées.
La plupart des opérateurs du langage impliquent une conversion préalable de leurs opérandes vers un type commun, qui a au moins la précision d'un int
. Même si deux opérandes sont de même type de précision inférieure à int
, comme short
, il y a une conversion en int
avant l'opération. Ainsi dans :
short a, b, c; c = a + b;
les valeurs de a
et b
sont converties en int
avant d'être additionnées. Le résultat, aussi de type int
, est ensuite affecté à la variable c
de type short
, ce qui peut potentiellement tronquer le résultat.
Notes et références
Portail de la programmation informatique