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 de char est fourni par le CHAR_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. */
C99
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
C99
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 .

C99

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.

C99
/* only two narrow or two wide string literals may be concatenated */
char* s = "Hello, " "World";
C99
/* 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";
C11
/* 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)

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 fonction void et renvoyant int ;
  • ptr : un pointeur sur un int ;
  • fp : un pointeur sur une fonction prenant int et retournant int ;
  • arr : un tableau de taille 10 d'un tableau de taille 20 de int ;
  • 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];


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow