C Language
Types de données
Recherche…
Remarques
- Bien que
char
soit obligatoire pour 1 octet, il n'est pas nécessaire que 1 octet soit de 8 bits (souvent appelé également octet ), même si la plupart des plates-formes informatiques modernes le définissent comme 8 bits. Le nombre de bits par de la mise en œuvre dechar
est fourni par leCHAR_BIT
macro, défini dans<limits.h>
. POSIX nécessite 1 octet pour 8 bits. - Les types entiers à largeur fixe doivent être utilisés de manière éparse, les types intégrés à C sont conçus pour être naturels sur chaque architecture, les types à largeur fixe ne doivent être utilisés que si vous avez explicitement besoin d'un entier spécifique (par exemple pour la mise en réseau).
Types entiers et constantes
Les entiers signés peuvent être de ces types (l' int
après short
ou long
est facultatif):
signed char c = 127; /* required to be 1 byte, see remarks for further information. */
signed short int si = 32767; /* required to be at least 16 bits. */
signed int i = 32767; /* required to be at least 16 bits */
signed long int li = 2147483647; /* required to be at least 32 bits. */
signed long long int li = 2147483647; /* required to be at least 64 bits */
Chacun de ces types d'entiers signés a une version non signée.
unsigned int i = 65535;
unsigned short = 2767;
unsigned char = 255;
Pour tous les types sauf la char
la version signed
est supposée si la partie signed
ou unsigned
est omise. Le type char
constitue un troisième type de caractère, différent du caractère signed char
et du caractère unsigned char
et la signature (ou non) dépend de la plate-forme.
Différents types de constantes entières (appelés littéraux dans le jargon C) peuvent être écrits dans des bases différentes et de différentes largeurs, en fonction de leur préfixe ou suffixe.
/* the following variables are initialized to the same value: */
int d = 42; /* decimal constant (base10) */
int o = 052; /* octal constant (base8) */
int x = 0xaf; /* hexadecimal constants (base16) */
int X = 0XAf; /* (letters 'a' through 'f' (case insensitive) represent 10 through 15) */
Les constantes décimales sont toujours signed
. Les constantes hexadécimales commencent par 0x
ou 0X
et les constantes octales commencent par 0
. Les deux derniers sont signed
ou unsigned
selon que la valeur correspond ou non au type signé.
/* suffixes to describe width and signedness : */
long int i = 0x32; /* no suffix represent int, or long int */
unsigned int ui = 65535u; /* u or U represent unsigned int, or long int */
long int li = 65536l; /* l or L represent long int */
Sans suffixe, la constante a le premier type qui correspond à sa valeur, c’est-à-dire qu’une constante décimale supérieure à INT_MAX
est de type long
si possible, ou long long
sinon.
Le fichier d'en-tête <limits.h>
décrit les limites des entiers comme suit. Leurs valeurs définies par la mise en œuvre doivent être égales ou supérieures (valeur absolue) à celles indiquées ci-dessous, avec le même signe.
Macro | Type | Valeur |
---|---|---|
CHAR_BIT | plus petit objet qui n'est pas un champ de bits (octet) | 8 |
SCHAR_MIN | signed char | -127 / - (2 7 - 1) |
SCHAR_MAX | signed char | +127 / 2 7 - 1 |
UCHAR_MAX | unsigned char | 255/2 8 - 1 |
CHAR_MIN | char | voir ci-dessous |
CHAR_MAX | char | voir ci-dessous |
SHRT_MIN | short int | -32767 / - (2 15 - 1) |
SHRT_MAX | short int | +32767 / 2 15 - 1 |
USHRT_MAX | unsigned short int | 65535/2 16 - 1 |
INT_MIN | int | -32767 / - (2 15 - 1) |
INT_MAX | int | +32767 / 2 15 - 1 |
UINT_MAX | unsigned int | 65535/2 16 - 1 |
LONG_MIN | long int | -2147483647 / - (2 31 - 1) |
LONG_MAX | long int | +2147483647 / 2 31 - 1 |
ULONG_MAX | unsigned long int | 4294967295/2 32 - 1 |
Macro | Type | Valeur |
---|---|---|
LLONG_MIN | long long int | -9223372036854775807 / - (2 63 - 1) |
LLONG_MAX | long long int | +9223372036854775807 / 2 63 - 1 |
ULLONG_MAX | unsigned long long int | 18446744073709551615/2 64 - 1 |
Si la valeur d'un objet de type char
sign- CHAR_MIN
est utilisée dans une expression, la valeur de CHAR_MIN
doit être la même que celle de SCHAR_MIN
et la valeur de CHAR_MAX
doit être identique à celle de SCHAR_MAX
. Si la valeur d'un objet de type char
ne se prolonge pas lorsqu'il est utilisé dans une expression, la valeur de CHAR_MIN
doit être 0 et la valeur de CHAR_MAX
doit être identique à celle de UCHAR_MAX
.
La norme C99 a ajouté un nouvel en-tête, <stdint.h>
, qui contient les définitions des entiers à largeur fixe. Voir l'exemple entier de largeur fixe pour une explication plus détaillée.
Littéraux de chaîne
Une chaîne littérale dans C est une séquence de caractères, terminée par un littéral zéro.
char* str = "hello, world"; /* string literal */
/* string literals can be used to initialize arrays */
char a1[] = "abc"; /* a1 is char[4] holding {'a','b','c','\0'} */
char a2[4] = "abc"; /* same as a1 */
char a3[3] = "abc"; /* a1 is char[3] holding {'a','b','c'}, missing the '\0' */
Les littéraux de chaîne ne sont pas modifiables (et peuvent en fait être placés dans une mémoire en lecture seule telle que .rodata). Tenter de modifier leurs valeurs entraîne un comportement indéfini.
char* s = "foobar";
s[0] = 'F'; /* undefined behaviour */
/* it's good practice to denote string literals as such, by using `const` */
char const* s1 = "foobar";
s1[0] = 'F'; /* compiler error! */
Plusieurs littéraux de chaîne sont concaténés au moment de la compilation, ce qui signifie que vous pouvez écrire des constructions comme celles-ci.
/* only two narrow or two wide string literals may be concatenated */
char* s = "Hello, " "World";
/* since C99, more than two can be concatenated */
/* concatenation is implementation defined */
char* s1 = "Hello" ", " "World";
/* common usages are concatenations of format strings */
char* fmt = "%" PRId16; /* PRId16 macro since C99 */
Les littéraux de chaîne, identiques aux constantes de caractères, prennent en charge différents jeux de caractères.
/* normal string literal, of type char[] */
char* s1 = "abc";
/* wide character string literal, of type wchar_t[] */
wchar_t* s2 = L"abc";
/* UTF-8 string literal, of type char[] */
char* s3 = u8"abc";
/* 16-bit wide string literal, of type char16_t[] */
char16_t* s4 = u"abc";
/* 32-bit wide string literal, of type char32_t[] */
char32_t* s5 = U"abc";
Types entiers de largeur fixe (depuis C99)
L'en-tête <stdint.h>
fournit plusieurs définitions de type entier à largeur fixe. Ces types sont facultatifs et ne sont fournis que si la plate-forme a un type entier de la largeur correspondante et si le type signé correspondant a une représentation à deux complément des valeurs négatives.
Reportez-vous à la section Remarques pour obtenir des conseils d'utilisation sur les types de largeur fixe.
/* commonly used types include */
uint32_t u32 = 32; /* exactly 32-bits wide */
uint8_t u8 = 255; /* exactly 8-bits wide */
int64_t i64 = -65 /* exactly 64 bit in two's complement representation */
Constantes à virgule flottante
Le langage C dispose de trois types réels de virgule flottante, float
, double
et long double
.
float f = 0.314f; /* suffix f or F denotes type float */
double d = 0.314; /* no suffix denotes double */
long double ld = 0.314l; /* suffix l or L denotes long double */
/* the different parts of a floating point definition are optional */
double x = 1.; /* valid, fractional part is optional */
double y = .1; /* valid, whole-number part is optional */
/* they can also defined in scientific notation */
double sd = 1.2e3; /* decimal fraction 1.2 is scaled by 10^3, that is 1200.0 */
L'en-tête <float.h>
définit différentes limites pour les opérations en virgule flottante.
L'arithmétique en virgule flottante est définie par l'implémentation. Cependant, la plupart des plates-formes modernes (arm, x86, x86_64, MIPS) utilisent les opérations à virgule flottante IEEE 754 .
C possède également trois types de virgule flottante complexes optionnels dérivés de ce qui précède.
Interprétation des déclarations
Une particularité syntaxique distinctive de C est que les déclarations reflètent l’utilisation de l’objet déclaré tel qu’il serait dans une expression normale.
L'ensemble d'opérateurs suivant avec une priorité et une associativité identiques est réutilisé dans les déclarants, à savoir:
- l'opérateur unaire
*
"dereference" qui désigne un pointeur; - l'opérateur binary
[]
"array subscription" qui désigne un tableau; - l'opérateur (1 + n) -ary
()
"fonction call" qui dénote une fonction; - le
()
regroupant les parenthèses qui remplacent la priorité et l’associativité des autres opérateurs listés.
Les trois opérateurs ci-dessus ont la priorité et l’associativité suivantes:
Opérateur | Priorité relative | Associativité |
---|---|---|
[] (abonnement tableau) | 1 | De gauche à droite |
() (appel de fonction) | 1 | De gauche à droite |
* (déréférence) | 2 | De droite à gauche |
Lors de l'interprétation des déclarations, il faut partir de l'identifiant extérieur et appliquer les opérateurs adjacents dans le bon ordre, comme indiqué dans le tableau ci-dessus. Chaque application d'un opérateur peut être remplacée par les mots anglais suivants:
Expression | Interprétation |
---|---|
thing[X] | un tableau de taille X de ... |
thing(t1, t2, t3) | une fonction prenant t1 , t2 , t3 et retournant ... |
*thing | un pointeur sur ... |
Il s'ensuit que le début de l'interprétation en anglais commence toujours par l'identifiant et se termine par le type qui se trouve à gauche de la déclaration.
Exemples
char *names[20];
[]
a priorité sur *
, donc l'interprétation est la suivante: names
est un tableau de taille 20 d'un pointeur sur char
.
char (*place)[10];
Dans le cas de l' utilisation de parenthèses pour modifier la priorité, le *
est appliqué en premier: place
est un pointeur sur un tableau de taille 10 de char
.
int fn(long, short);
Il n'y a pas de priorité à se soucier ici: fn
est une fonction qui prend du long
, short
et qui renvoie int
.
int *fn(void);
Le ()
est appliqué en premier: fn
est une fonction qui prend un void
et renvoie un pointeur sur int
.
int (*fp)(void);
Substitution de la priorité de ()
: fp
est un pointeur vers une fonction prenant void
et le retour int
.
int arr[5][8];
Les tableaux multidimensionnels ne font pas exception à la règle; les opérateurs []
sont appliqués dans l'ordre de gauche à droite en fonction de l'associativité de la table: arr
est un tableau de taille 5 d'un tableau de taille 8 de int
.
int **ptr;
Les deux opérateurs de déréférencement ont la même priorité, de sorte que l'associativité prend effet. Les opérateurs sont appliqués dans l'ordre de droite à gauche: ptr
est un pointeur sur un pointeur vers un int
.
Plusieurs déclarations
La virgule peut être utilisée comme séparateur (* pas * agissant comme l'opérateur de virgule) afin de délimiter plusieurs déclarations au sein d'une même déclaration. La déclaration suivante contient cinq déclarations:int fn(void), *ptr, (*fp)(int), arr[10][20], num;
Les objets déclarés dans l'exemple ci-dessus sont les suivants:
-
fn
: une fonctionvoid
et renvoyantint
; -
ptr
: un pointeur sur unint
; -
fp
: un pointeur sur une fonction prenantint
et retournantint
; -
arr
: un tableau de taille 10 d'un tableau de taille 20 deint
; -
num
:int
.
Interprétation alternative
Comme les déclarations sont utilisées en miroir, une déclaration peut également être interprétée en fonction des opérateurs pouvant être appliqués sur l'objet et du type résultant final de cette expression. Le type qui se trouve à gauche est le résultat final obtenu après application de tous les opérateurs.
/*
* Subscripting "arr" and dereferencing it yields a "char" result.
* Particularly: *arr[5] is of type "char".
*/
char *arr[20];
/*
* Calling "fn" yields an "int" result.
* Particularly: fn('b') is of type "int".
*/
int fn(char);
/*
* Dereferencing "fp" and then calling it yields an "int" result.
* Particularly: (*fp)() is of type "int".
*/
int (*fp)(void);
/*
* Subscripting "strings" twice and dereferencing it yields a "char" result.
* Particularly: *strings[5][15] is of type "char"
*/
char *strings[10][20];