Suivez-nous sur X
|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : C - les types C ANSI, les modificateurs, les types de données complexes
(Article écrit par Diallo Barrou et extrait d'Amiga News - septembre 1993)
|
|
Après ces vacances d'été rudement méritées, reprenons le chemin du C et de ses subtilités en abordant
les types de données et les structures complexes comme prévu la fois dernière.
Les types du C ANSI
Le C possède plusieurs types bien distincts et leur connaissance est primordiale car l'on réservera
plus ou moins de mémoire selon le type de données utilisé. Concrètement, un type est une règle de
comportement dans les calculs et une règle d'allocation dans les déclarations. Tout de suite,
en voici la petite liste, ainsi que les caractéristiques de chacun selon la norme ANSI, qui, je
le rappelle, vaut pour tous les compilateurs standard.
- void : le type "rien", utilisé pour dire qu'une fonction ne renvoie rien par exemple.
Mais aussi, pour déclarer ce qu'on appelle des "pointeurs génériques". Nous en reparlerons plus tard.
- float : utilisé pour les nombres à virgule de précision maximale de six décimales.
- double : même chose que pour les "float" mais avec une précision de dix décimales.
- int : cette fois-ci on peut déclarer un entier, stocké sur 16 bits minimum, c'est-à-dire de
-32768 à +32767. Attention, la taille d'un "int" est fortement liée au matériel (il peut passer de
16 bits pour un 68000 ou un i80286 à 64 bits pour un i860). Mais tel n'est pas notre propos aujourd'hui.
- char : ce type permet de stocker la valeur d'un caractère (1 octet), c'est-à-dire la totalité de la
table ASCII standard (0 à 127). Attention, cela peut ne pas être suffisant pour d'autres alphabets comme
les Kanji japonais.
Et puis, c'est tout. Rien à signaler jusque-là ? J'entends d'ici hurler les programmeurs en C, qui
n'en croient pas leurs yeux. Et bien sûr, nous pouvons moduler ces types selon les différents besoins de
stockage et ce qui suit les exemples sont des "modificateurs" et non des types ! ;-)
Exemple d'utilisation :
Plusieurs remarques sont à formuler :
1. La fonction principale "main" ne prend pas d'arguments et n'en renvoie pas (void).
2. On peut déclarer une variable et en même temps lui affecter une valeur.
3. Une constante réelle peut être écrite sous la forme "scientifique" avec un "e" ou "E"
signifiant l'exposant qui peut être positif ou négatif : 3.1E-6 est égal à "3,1 fois dix exposant -6" = 0,0000031.
4. Une constante réelle est considérée comme un type "double".
5. La variable "entier" a été déclarée, mais elle ne contient pas de valeurs cohérentes jusqu'à ce qu'on
lui en affecte une. Attention : déclarer une variable ne signifie pas obligatoirement qu'elle est égale à 0 !
6. Les déclarations de variables se font toujours en début de fonction, ou de programme (contraireMent au C++),
avant toute autre instruction.
7. Le nom de la variable signifie son contenu et le nom précédé du signe "&", signifie son adresse en mémoire.
Nous pouvons observer "&entier" dans la fonction "scanf" qui permet de saisir une donnée au clavier et de la
stocker dans l'adresse d'une variable.
Les modificateurs
Nous voilà arrivés au stade du détail sur les types. Le C n'est pas riche en types différents
(cinq au total), mais par contre, nous pouvons les complémenter de "modificateurs" qui étendront leurs
caractéristiques ! Voici les quatre modificateurs du C qui se placent avant le type. Notons qu'ils sont
propres à certains types et qu'ils peuvent être utilisés seuls parfois :
- short : s'il est seul, il est égal à "short int" (16 bits), mais peut être utilisé devant un
"char" ou un "int". Exemple : "short char chr;". La valeur de la variable "chr" doit être comprise entre 0 et 127.
- long : seul, il équivaut à un "long int" (32 bits), mais il peut aussi être utilisé devant les types
"float" (ce qui donne un "double"), ou devant un "char", ce qui étend ce type à l'intervalle (0-256).
- signed : peut être utilisé devant "char", "int" et bien sûr "long int". Il permet de forcer
l'intervalle des valeurs possibles autour de 0. Exemple : "signed char chr;". La variable "chr" peut contenir
des valeurs entre -128 et 127.
- unsigned char : il s'applique comme "signed" devant le "char", "int" et "long int"
et force la borne inférieure de l'intervalle des valeurs à 0. Exemple : "unsigned char chr;".
La variable "chr" peut contenir des valeurs de 0 à 255.
Voilà pour les modificateurs de types. D'autres combinaisons sont possibles comme pour déclarer un
entier de 32 bits non signé (dont on utilise le dernier bit pour coder le reste du nombre au
lieu du signe). On écrira :
Remarque
Il est possible de passer d'un type à l'autre grâce à ce qu'on appelle le "cast" qui se traduit
par une conversion d'une expression en un type donné en la précédant d'un type entre parenthèses :
Bien sûr chaque type possède une taille bien définie. Grâce à l'opérateur "sizeof", vous pourrez connaître
la taille de chacun d'eux suivant votre machine et votre compilateur :
En parlant d'opérateurs, nous allons voir rapidement ce qu'il en est en C, avant d'attaquer les types de
données crées par l'utilisateur. Évidemment, les quatre opérateurs arithmétiques de base sont présents
(+, -, *, /), mais observez ces notations qui permettent toutes d'ajouter 1 à la variable "a" :
Les opérateurs unaires correspondants à la soustraction existent aussi : a-- ; --a;
Le "%" est un opérateur de modulo qui renvoit le reste de la division entre deux nombres entiers : resultat = 5%3;
Les avantages des opérateurs
Pauvre en instructions, le C recèle des opérateurs puissants comme les décalages et les opérations logiques :
Notons que les nombres en hexadécimal se préfixent de "0x" ou "0X" et que les nombres en octal (base 8)
commencent par 0.
Sans oublier les combinaisons "Opération =" :
Exemple : "resultat <<= 2" est équivalent à "resultat = resultat <<2" qui décale de 2 bits
vers la gauche le contenu de la variable "resultat".
Les programmeurs en assembleur y trouveront leur compte à coup de décalages, d'opérations logiques et
de pré/post-incrémentation ou décrémentation ! La seule opération qui fasse défaut est la rotation
bit à bit (rol ou ror en 68000), mais cela serait un bon exercice de la programmer !
Les types de données complexes
N'ayez crainte, ce n'est que l'aboutissement de ce qui précède ! Nous parlons tout d'abord de structures
avec le mot clef "struct" qui permettent de réunir un ensemble de données de types semblables ou différents d'un
même thème dans une seule variable. Les pascaliens reconnaitront vite les fameux "RECORD OF".
Un exemple serait plus clair :
Et voilà, nous avons défini une structure nommée "PERSONNE" qui contient, la place pour un nom, un
prénom, un âge et une taille. La variable "toi" est de ce type-là.
Notez la notation [] qui permet de faire des tableaux d'un type donné :
Attention : en C, les tableaux de taille "n" commencent à 0 et se terminent à n-1,
le tableau famille par exemple, commence à famille[0] pour le premier membre et se termine
à famille[7] pour le dernier. Un dépassement peut être fatal et entraîner un plantage.
Comment utiliser cette structure ? Pour accéder à un champ d'une structure, il suffit de faire
suivre le nom de la variable par un point et par le nom du champ en question :
Exemple complet :
Assez pour cette fois-ci, vous avez maintenant du pain sur la planche pour expérimenter tout cela !
La prochaine fois nous continuerons sur les types complexes car vous n'êtes pas au bout de vos
surprises ! En attendant le mois prochain, voici un petit exercice en guise d'entraînement :
que fais cette macro ?
Résultats et explications la prochaine fois !
|