Arithmetic types
(Voir aussi type pour un aperçu du système de types et la liste des utilitaires liés aux types fournis par la bibliothèque C.)
Type booléenNotez que la conversion vers _Bool (jusqu'à C23) bool (depuis C23) ne fonctionne pas de la même manière que la conversion vers d'autres types entiers : ( bool ) 0.5 s'évalue à true , tandis que ( int ) 0.5 s'évalue à 0 . |
(depuis C99) |
Types de caractères
-
- signed char — type pour la représentation de caractères signés.
- unsigned char — type pour la représentation de caractères non signés. Également utilisé pour inspecter les représentations d'objets (mémoire brute).
- char — type pour la représentation de caractères. Équivalent à signed char ou unsigned char (le choix étant défini par l'implémentation et pouvant être contrôlé par un commutateur en ligne de commande du compilateur), mais char est un type distinct, différent à la fois de signed char et de unsigned char .
Notez que la bibliothèque standard définit également typedef les noms wchar_t , char16_t et char32_t (depuis C11) pour représenter les caractères larges et char8_t pour les caractères UTF-8 (depuis C23) .
Types entiers
-
- short int (également accessible sous short , peut utiliser le mot-clé signed )
- unsigned short int (également accessible sous unsigned short )
- int (également accessible sous signed int )
- Ceci est le type entier le plus optimal pour la plateforme, et il est garanti d'être d'au moins 16 bits. La plupart des systèmes actuels utilisent 32 bits (voir les modèles de données ci-dessous).
- unsigned int (également accessible sous unsigned ), la contrepartie non signée de int , implémentant l'arithmétique modulo. Convient pour les manipulations de bits.
- long int (également accessible sous long )
- unsigned long int (également accessible sous unsigned long )
|
(depuis C99) |
|
(depuis C23) |
Note : comme pour tous les spécificateurs de type, tout ordre est autorisé : unsigned long long int et long int unsigned long désignent le même type.
Le tableau suivant résume tous les types entiers disponibles et leurs propriétés :
| Spécificateur de type | Type équivalent | Largeur en bits par modèle de données | ||||
|---|---|---|---|---|---|---|
| Norme C | LP32 | ILP32 | LLP64 | LP64 | ||
|
char
|
char |
au moins
8 |
8 | 8 | 8 | 8 |
|
signed
char
|
signed char | |||||
|
unsigned
char
|
unsigned char | |||||
|
short
|
short int |
au moins
16 |
16 | 16 | 16 | 16 |
|
short
int
|
||||||
|
signed
short
|
||||||
|
signed
short
int
|
||||||
|
unsigned
short
|
unsigned short int | |||||
|
unsigned
short
int
|
||||||
|
int
|
int |
au moins
16 |
16 | 32 | 32 | 32 |
|
signé
|
||||||
|
signed
int
|
||||||
|
unsigned
|
unsigned int | |||||
|
unsigned
int
|
||||||
|
long
|
long int |
au moins
32 |
32 | 32 | 32 | 64 |
|
long
int
|
||||||
|
signed
long
|
||||||
|
signed
long
int
|
||||||
|
unsigned
long
|
unsigned long int | |||||
|
unsigned
long
int
|
||||||
|
long
long
|
long
long
int
(C99) |
au moins
64 |
64 | 64 | 64 | 64 |
|
long
long
int
|
||||||
|
signed
long
long
|
||||||
|
signed
long
long
int
|
||||||
|
unsigned
long
long
|
unsigned
long
long
int
(C99) |
|||||
|
unsigned
long
long
int
|
||||||
Outre les nombres minimaux de bits, la norme C garantit que
-
1
==
sizeof
(
char
)
≤sizeof ( short )≤sizeof ( int )≤sizeof ( long )≤sizeof ( long long ) .
` n'est pas traduit (les symboles ≤ restent inchangés)
- Les termes spécifiques au C++ (sizeof, char, short, int, long) ne sont pas traduits
- La structure et le formatage d'origine sont préservés
Note : cela permet le cas extrême où les bytes ont une taille de 64 bits, tous les types (y compris char ) ont une largeur de 64 bits, et sizeof renvoie 1 pour chaque type.
Note : l'arithmétique entière est définie différemment pour les types entiers signés et non signés. Voir les opérateurs arithmétiques , en particulier les dépassements d'entiers .
Modèles de données
Les choix effectués par chaque implémentation concernant les tailles des types fondamentaux sont collectivement appelés modèle de données . Quatre modèles de données ont été largement adoptés :
Systèmes 32 bits :
-
- LP32 ou 2/4/4 ( int est 16-bit, long et pointeur sont 32-bit)
-
- API Win16
- ILP32 ou 4/4/4 ( int , long , et pointeur sont 32-bit);
-
- API Win32
- Systèmes Unix et de type Unix (Linux, Mac OS X)
Systèmes 64 bits :
-
- LLP64 ou 4/4/8 ( int et long sont 32 bits, le pointeur est 64 bits)
-
- API Win64
- LP64 ou 4/8/8 ( int est 32 bits, long et le pointeur sont 64 bits)
-
- Systèmes Unix et de type Unix (Linux, Mac OS X)
D'autres modèles sont très rares. Par exemple, ILP64 ( 8/8/8 : int , long , et les pointeurs sont 64 bits) n'est apparu que dans certains systèmes Unix 64 bits anciens (par exemple Unicos sur Cray ).
Notez que les types entiers de largeur exacte sont disponibles dans <stdint.h> depuis C99.
Types flottants réels
C possède trois ou six (depuis C23) types pour représenter les valeurs réelles en virgule flottante :
-
- float — type à virgule flottante simple précision. Correspond au format IEEE-754 binary32 s'il est pris en charge.
- double — type à virgule flottante double précision. Correspond au format IEEE-754 binary64 s'il est pris en charge.
-
long
double
— type à virgule flottante étendue précision. Correspond au
format IEEE-754
binary128
s'il est pris en charge, sinon correspond au
format IEEE-754
binary64
-étendu
s'il est pris en charge, sinon correspond à un format à virgule flottante étendu non IEEE-754 tant que sa précision est meilleure que
binary64
et sa plage au moins aussi bonne que
binary64
, sinon correspond au format IEEE-754
binary64
.
- binary128 est utilisé par certaines implémentations HP-UX, SPARC, MIPS, ARM64 et z/OS.
- Le format IEEE-754 binary64 -étendu le plus connu est le format étendu x87 80-bit. Il est utilisé par de nombreuses implémentations x86 et x86-64 (une exception notable est MSVC, qui implémente long double dans le même format que double , c'est-à-dire binary64 ).
|
(depuis C23) |
Les types à virgule flottante peuvent prendre en charge des valeurs spéciales :
- l'infini (positif et négatif), voir INFINITY
- le zéro négatif , - 0.0 . Il est égal au zéro positif, mais est significatif dans certaines opérations arithmétiques, par exemple 1.0 / 0.0 == INFINITY , mais 1.0 / - 0.0 == - INFINITY )
- non-nombre (NaN), qui n'est égal à rien (y compris lui-même). Plusieurs motifs binaires représentent les NaNs, voir nan , NAN . Notez que C ne traite pas spécialement les NaNs signalés (spécifiés par IEEE-754) et considère tous les NaNs comme silencieux.
Les nombres réels à virgule flottante peuvent être utilisés avec
les opérateurs arithmétiques
+
-
/
*
et diverses fonctions mathématiques de
<math.h>
. Les opérateurs intégrés et les fonctions de bibliothèque peuvent lever des exceptions de virgule flottante et définir
errno
comme décrit dans
math_errhandling
.
Les expressions en virgule flottante peuvent avoir une plage et une précision supérieures à celles indiquées par leurs types, voir FLT_EVAL_METHOD . L'assignation , return , et cast forcent la plage et la précision à celles associées au type déclaré.
Les expressions en virgule flottante peuvent également être contractées , c'est-à-dire calculées comme si toutes les valeurs intermédiaires avaient une plage et une précision infinies, voir #pragma STDC FP_CONTRACT .
Certaines opérations sur les nombres à virgule flottante sont affectées par et modifient l'état de l'environnement de virgule flottante (notamment, la direction d'arrondi).
Conversions implicites sont définies entre les types flottants réels et les types entiers, complexes et imaginaires.
Voir Limites des types à virgule flottante et la bibliothèque <math.h> pour des détails supplémentaires, limites et propriétés des types à virgule flottante.
Types à virgule flottante complexesLes types à virgule flottante complexes modélisent les nombres complexes mathématiques, c'est-à-dire les nombres qui peuvent s'écrire comme la somme d'un nombre réel et d'un nombre réel multiplié par l'unité imaginaire : a + bi Les trois types complexes sont
Remarque : comme pour tous les spécificateurs de type, tout ordre est autorisé : long double complex , complex long double , et même double complex long désignent le même type.
Exécuter ce code
Sortie : 1/(1.0+2.0i) = 0.2-0.4i
Chaque type complexe possède la même représentation d'objet et les mêmes exigences d'alignement qu'un tableau de deux éléments du type réel correspondant ( float pour float complex , double pour double complex , long double pour long double complex ). Le premier élément du tableau contient la partie réelle, et le deuxième élément du tableau contient la composante imaginaire.
Les nombres complexes peuvent être utilisés avec
les opérateurs arithmétiques
L'incrémentation et la décrémentation ne sont pas définies pour les types complexes. Les opérateurs relationnels ne sont pas définis pour les types complexes (il n'existe pas de notion de "inférieur à").
Afin de soutenir le modèle un-infini de l'arithmétique des nombres complexes, C considère toute valeur complexe avec au moins une partie infinie comme une infini même si son autre partie est un NaN, garantit que tous les opérateurs et fonctions respectent les propriétés fondamentales des infinis et fournit cproj pour mapper tous les infinis vers l'infini canonique (voir opérateurs arithmétiques pour les règles exactes).
Exécuter ce code
#include <complex.h> #include <math.h> #include <stdio.h> int main(void) { double complex z = (1 + 0*I) * (INFINITY + I*INFINITY); // la formule théorique donnerait // (1+i0)(∞+i∞) ⇒ (1×∞ – 0×∞) + i(0×∞+1×∞) ⇒ NaN + I*NaN // mais C donne un infini complexe printf("%f%+f*i\n", creal(z), cimag(z)); // la formule théorique donnerait // cexp(∞+iNaN) ⇒ exp(∞)×(cis(NaN)) ⇒ NaN + I*NaN // mais C donne ±∞+i*nan double complex y = cexp(INFINITY + I*NAN); printf("%f%+f*i\n", creal(y), cimag(y)); } Sortie possible : inf+inf*i inf+nan*i C traite également les multiples infinis de manière à préserver l'information directionnelle lorsque cela est possible, malgré les limitations inhérentes à la représentation cartésienne : multiplier l'unité imaginaire par l'infini réel donne l'infini imaginaire correctement signé : i × ∞ = i∞. De plus, i × (∞ – i∞) = ∞ + i∞ indique le quadrant raisonnable.
Types flottants imaginairesLes types flottants imaginaires modélisent les nombres imaginaires mathématiques, c'est-à-dire des nombres qui peuvent s'écrire comme un nombre réel multiplié par l'unité imaginaire : bi Les trois types imaginaires sont
Note : comme pour tous les spécificateurs de type, tout ordre est autorisé : long double imaginary , imaginary long double , et même double imaginary long désignent le même type.
Exécuter ce code
Sortie : 1/(3.0i) = -0.3i
Chacun des trois types imaginaires possède la même représentation d'objet et les mêmes exigences d'alignement que son type réel correspondant ( float pour float imaginary , double pour double imaginary , long double pour long double imaginary ). Note : bien que les types imaginaires soient distincts et non compatibles avec leurs types réels correspondants, ce qui interdit l'aliasing.
Les nombres imaginaires peuvent être utilisés avec
les opérateurs arithmétiques
L'incrémentation et la décrémentation ne sont pas définies pour les types imaginaires.
Les nombres imaginaires permettent d'exprimer tous les nombres complexes en utilisant la notation naturelle x + I * y (où I est défini comme _Imaginary_I ). Sans les types imaginaires, certaines valeurs complexes spéciales ne peuvent pas être créées naturellement. Par exemple, si I est défini comme _Complex_I , alors écrire 0.0 + I * INFINITY donne NaN comme partie réelle, et CMPLX ( 0.0 , INFINITY ) doit être utilisé à la place. Il en va de même pour les nombres avec une composante imaginaire de zéro négatif, qui sont significatifs lors de l'utilisation des fonctions de bibliothèque avec des coupures de branche, telles que csqrt : 1.0 - 0.0 * I donne une composante imaginaire de zéro positif si I est défini comme _Complex_I et la partie imaginaire de zéro négatif nécessite l'utilisation de CMPLX ou conj . Les types imaginaires simplifient également les implémentations ; la multiplication d'un imaginaire par un complexe peut être implémentée directement avec deux multiplications si les types imaginaires sont pris en charge, au lieu de quatre multiplications et deux additions. |
(depuis C99) |
Mots-clés
- bool , true , false , char , int , short , long , signed , unsigned , float , double .
- _Bool , _BitInt , _Complex , _Imaginary , _Decimal32 , _Decimal64 , _Decimal128 .
Plage de valeurs
Le tableau suivant fournit une référence pour les limites des représentations numériques courantes.
Avant C23, la norme C autorisait toute représentation d'entiers signés, et la plage minimale garantie des entiers signés de N bits était de
-(2
N-1
-1)
à
+2
N-1
-1
(par exemple
-127
à
127
pour un type signé 8 bits), ce qui correspond aux limites du
complément à un
ou de la
représentation signe-magnitude
.
Cependant, tous les modèles de données populaires (y compris ILP32, LP32, LP64, LLP64) et presque tous les compilateurs C utilisent
la représentation en complément à deux
(les seules exceptions connues sont certains compilateurs pour UNISYS), et depuis C23, c'est la seule représentation autorisée par la norme, avec la plage garantie de
-2
N-1
à
+2
N-1
-1
(par exemple
-128
à
127
pour un type signé 8 bits).
| Type | Taille en bits | Format | Plage de valeurs | |
|---|---|---|---|---|
| Approximatif | Exact | |||
| caractère | 8 | signé | −128 à 127 | |
| non signé | 0 à 255 | |||
| 16 | UTF-16 | 0 à 65535 | ||
| 32 | UTF-32 | 0 à 1114111 ( 0x10ffff ) | ||
| entier | 16 | signé | ± 3.27 · 10 4 | −32768 à 32767 |
| non signé | 0 à 6.55 · 10 4 | 0 à 65535 | ||
| 32 | signé | ± 2.14 · 10 9 | −2,147,483,648 à 2,147,483,647 | |
| non signé | 0 à 4.29 · 10 9 | 0 à 4,294,967,295 | ||
| 64 | signé | ± 9.22 · 10 18 | −9,223,372,036,854,775,808 à 9,223,372,036,854,775,807 | |
| non signé | 0 à 1.84 · 10 19 | 0 à 18,446,744,073,709,551,615 | ||
|
virgule flottante
binaire |
32 | IEEE-754 |
|
|
| 64 | IEEE-754 |
|
|
|
| 80 [note 1] | x86 |
|
|
|
| 128 | IEEE-754 |
|
|
|
|
virgule flottante
décimale |
32 | IEEE-754 |
|
|
| 64 | IEEE-754 |
|
||
| 128 | IEEE-754 |
|
||
- ↑ La représentation objet occupe généralement 96/128 bits sur les plateformes 32/64 bits respectivement.
Note : les plages réelles (par opposition aux minimales garanties) sont disponibles dans les en-têtes de la bibliothèque <limits.h> et <float.h> .
Voir aussi
|
Documentation C++
pour
Types fondamentaux
|