Introduction au langage C/Types
Définition
[modifier | modifier le wikicode]En C, contrairement à PHP ou à JavaScript, une variable est dite typée et ne peut contenir que des valeurs de ce type. On peut déjà classer les types numériques en 2 catégories :
- Les types contenant des entiers (short, integer, long)
- Les types contenant des décimaux (float, double : à virgule flottante)
En clair, un type est un attribut de la variable.
Conseils de codage à respecter : c_num_1, c_num_2
Types de base
[modifier | modifier le wikicode]Différents types
[modifier | modifier le wikicode]Le tableau suivant présente quelques types du langage C. Les tailles et valeurs sont données à titre d'exemple et dépendent de votre architecture informatique. Les limites de chaque type sont données dans le fichier d'include limits.h : CHAR_BIT, CHAR_MAX, CHAR_MIN...
Type | Description | Taille (*) | Valeur |
---|---|---|---|
void | Type générique | ||
char | caractère/octet (†) | 1 octets | comme signed ou unsigned char |
unsigned char | caractère/octet (†) non signé | 1 octets | 0 à 255 |
signed char | caractère/octet (†) signé | 1 octets | -128 à 127[1][2] |
short | entier court signé | 2 octets | -32 768 à 32 767 |
unsigned short | entier non signé | 2 octets | 0 à 65 535 |
int | entier signé | 2 ou 4 octets | (en fonction du compilateur) |
unsigned | entier non signé | 2 ou 4 octets | (en fonction du compilateur) |
long | entier signé long | 4 octets | -2 147 483 648 à 2 147 483 647 |
unsigned long | entier non signé long | 4 octets | 0 à 4 294 967 295 (2^32-1) |
float | flottant (‡) | 4 octets | Mantisse : +- 6 chiffres significatifs |
double | flottant (‡) | 8 octets | Mantisse : +- 12 chiffres significatifs |
long double | flottant (‡) | 10 octets |
Remarques :
- (†) Pour des raisons historiques on appelle caractère ce qui en pratique est un octet. Le caractère d'une application utilisateur peut maintenant être codé autrement lorsqu’il nécessite plusieurs octets.
- (*) Le nombres d'octets de chaque type dépend du compilateur, de ses options et de l'architecture de la machine cible.
- L'opérateur sizeof retourne la taille en bytes de son paramètre : type ou variable. Cette taille est de type size_t, le type char est l'unité de mesure.
- Une règle : sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
- Les valeurs min et max des types caractère et entier se trouvent dans des constantes du fichier d'include limits.h : INT_MIN, INT_MAX, LONG_MIN...
- (‡) Pour les flottants, voir float.h : FLT_MIN, FLT_MAX, DBL_MIN...
Conversion de type
[modifier | modifier le wikicode]En C, les changements de type dans les expressions sont réalisées de façon automatique avec parfois des pertes de précision dans les calculs et d’autre problèmes numériques. Pour rendre les expressions homogènes, on convertit les variables dans le même type. On parle de cast pour cette conversion en écrivant (type_souhaité)variable.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
(void)printf("4 / 5 = %f ou (float)4 / (float)5 = %f\n",
(float)(4/5), (float)4 / (float)5);
return EXIT_SUCCESS;
}
Affiche :
4 / 5 = 0.000000 ou (float)4 / (float)5 = 0.800000
Nouveaux types introduits par C99
[modifier | modifier le wikicode]La norme ISO C99, section 7.8 a introduit de nouveaux types, pour les entiers signés ou non, qui permettent d'améliorer la portabilité des programmes. Les includes stdint.h et inttypes.h permettent de les utiliser.
/*
Nom : typec99.c
Auteur : Thierry46
Role : Manipulation de types C99
Pour produire un exécutable avec le compilateur libre GCC :
gcc -Wall -pedantic -std=c99 -o typec99.exe typec99.c
Pour exécuter, tapez : ./typec99.exe
Version : 1.0 du 14/5/2008
Licence : GNU GPL
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
int main(void)
{
int_fast16_t n1, n2, resu;
n1 = INT16_C(300);
n2 = INT16_C(400);
resu = n1 + n2;
(void)printf("n1 = %"PRIdFAST16"\n"
"n2 = %"PRIdFAST16"\n"
"n1 + n2 = %"PRIdFAST16"\n",
n1, n2, resu);
// Impression des limites pour les nombres entiers
(void)printf("INT_FAST16_MAX = %"PRIdFAST16"\n", INT_FAST16_MAX);
(void)printf("INTMAX_MAX = %"PRIdMAX"\n", INTMAX_MAX);
return EXIT_SUCCESS;
}
Affiche :
n1 = 300 n2 = 400 n1 + n2 = 700 INT_FAST16_MAX = 32767 INTMAX_MAX = 9223372036854775807
Explications :
int_fast16_t n1, n2, resu;
déclare trois entiers signés 16 bits. Il est demandé de choisir un type machine d'au moins 16 bits qui assure une bonne performance de calcul (fast).n1 = INT16_C(300);
initialise n1 en utilisant la macro INT16_C(valeur) pour créer une constante du type correspondant.(void)printf("n1 = %"PRIdFAST16"\n"
utilise dans le format d'impression deprintf
l'indicateur de conversion PRIdFAST16 défini dans inttypes.h qui signifie :- PRI : indicateur pour les fonctions de la famille
printf
. Pour la famillescanf
se serait SCN - d : spécificateur classique de conversion, on pourrait aussi utiliser : i, o, x...
- FAST : pour un type C99 fast (rapide à calculer). il existe aussi LEAST.
- 16 : Nombre de bit minimum pour le stockage.
- PRI : indicateur pour les fonctions de la famille
(void)printf("INT_FAST16_MAX = %"PRIdFAST16"\n", INT_FAST16_MAX);
: cette instruction affiche le plus grand entier INT_FAST16_MAX stockable dans le type int_fast16_t en utilisant le spécificateur de format adapté PRIdFAST16. INT_FAST16_MIN contient elle la plus petite valeur négative de ce type.(void)printf("INTMAX_MAX = %"PRIdMAX"\n", INTMAX_MAX);
: cette instruction affiche le plus grand entier INTMAX_MAX stockable dans le type intmax_t en utilisant le spécificateur de format adapté PRIdMAX.- Pour utiliser des entiers non signés, faites précéder les types par u et les constantes par U.
Tableau
[modifier | modifier le wikicode]Il existe trois types de tableaux :
- les tableaux statiques, dont la taille est connue à la compilation;
- les tableaux de longueur variable ou VLA (Variable Length Array) introduits par la norme C99.
- les tableaux dynamiques, dont la taille est connue à l'exécution.
Nous ne nous intéresserons pour l'instant qu'aux tableaux statiques, les tableaux dynamiques seront présentés avec les pointeurs.
Note : les indices commencent à 0.
Exemple d’utilisation de tableau :
/*
Nom : tableau.c
Role : Utilisation de tableau.
Paramètres : non pris en compte.
Code retour : 0 (EXIT_SUCCESS)
Pour produire un exécutable avec le compilateur libre GCC :
gcc -o tableau.exe tableau.c
Pour exécuter, tapez : ./tableau.exe
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char argv[])
{
/* Définition du tableau d'entiers et initialisation */
int table[] = {0, 1, 2, 3, 4};
/* Modification de l'élément d'indice 0 */
table[0] = 5;
/* Écriture des éléments d'indice 0 et 1 */
(void)printf("table[0]=%d, table[1]=%d\n",
table[0], table[1]);
(void)puts("Fin du programme tableau");
return EXIT_SUCCESS;
}
À l'exécution :
$ ./tableau.exe table[0]=5, table[1]=1 Fin du programme tableau
Chaîne de caractères
[modifier | modifier le wikicode]Une chaîne de caractère peut être considérée comme un tableau de caractères/octets ou un espace mémoire terminé par un caractère/octet de valeur 0. Elle peut être initialisée par une constante littérale entre guillemets doubles "…"
. Elles peuvent contenir des caractères spéciaux codés sous forme de séquence d'échappement. Elles peuvent aussi contenir des caractères normaux codés sous la forme de plusieurs octets, c’est typiquement le cas lors de l’utilisation du format utf8.
Séquences d'échappement
caractère | signification | caractère | signification | caractère | signification | caractère | signification |
---|---|---|---|---|---|---|---|
\a | Sonnerie | \\ | Trait oblique | \b | Curseur arrière | \? | Point d'interrogation |
\t | Tabulation | \' | Apostrophe | \n | Nouvelle ligne | \" | guillemets |
\r | retour au début de ligne | \f | saut de page (imprimante) | \0 | Fin d'une chaine de caractère | \v | Tabulation verticale |
Les fonctions décrites dans l'include string.h facilitent la manipulation des chaines.
Structure
[modifier | modifier le wikicode]Les structures représentent un type particulier. Elles sont un conteneur pour une ou plusieurs variables, pouvant être de types différents. On les définit dans les fichiers d'entête ou au début du programme.
/*
Nom : structure.c
Role : Utilisation de structure.
Paramètres : non pris en compte.
Code retour : 0 (EXIT_SUCCESS)
Pour produire un exécutable avec le compilateur libre GCC :
gcc -o structure.exe structure.c
Pour exécuter, tapez : ./structure.exe
*/
#include <stdio.h>
#include <stdlib.h>
struct CLIENT
{
char nom[30];
float solde;
};
int main(int argc, char argv[])
{
struct CLIENT cl={"Smith", 15.5}; // déclaration + initialisation
/* Exemple d’utilisation des membres de la structure */
(void)printf("Nom : %s\nSolde : %f\n", cl.nom, cl.solde);
(void)puts("Fin du programme structure");
return EXIT_SUCCESS;
}
Le résultat :
$ ./structure.exe Nom : Smith Solde : 15.500000 Fin du programme structure
TP
[modifier | modifier le wikicode]