Chapitre 9: Les types avancées [Partie I]

Le langage C nous permet de créer nos propres types de variables. Cela peut devenir essentiel lorsque l’on souhaite programmer de gros programme par exemple. Nous verrons donc comment faire ceci.

Nous apprendrons tout d’abord à créer une structure et à l’utiliser dans nos programmes, puis nous ferons de même avec les énumérations et les unions. Nous parlerons aussi de typedef

         1 – Créer et utiliser une structure

    Une structure est en fait un regroupement de variables, de n’importe quels types, ainsi une structure peut contenir des variables de type int, char, double, …
Contrairement aux tableaux qui eux obligent aux éléments de ce tableau d’être tous du même type.

Sans plus attendre voyons comment créer une structure.

Tout d’abord il faut savoir qu’il est préférable de créer une structure en dehors d’une fonction car l’avantage des structures c’est qu’elles permettent un accès à leurs attributs (= sous-variables qu’elles contiennent) qui s’étend sur toutes les fonctions du programme.
Ainsi si vous créez une structure dans une fonction, seule celle-ci y’aura accès.

Voici la syntaxe utilisée pour définir une structure :

Code c:
struct MaStructure {
int var1;
long var2;
double varN;
};


On utilise le mot-clé struct suivi du nom que l’on souhaite donnée à notre structure (ici MaStructure [par convention, les noms données aux structures commencent par une majuscule afin de ne pas les confondre avec une variable]), ensuite on ouvre une accolade on remplie la structure des différentes sous-variables qu’on souhaite utilisées. Puis on referme l’accolade et on n’oublie surtout pas de mettre un point-virgule !

Vous voyez ici qu’on créer une structure composée de 3 sous-variables de types différents.

Maintenant que notre structure est créer il va falloir qu’on initialise nos sous-variables.

Attention on ne peut pas faire comme cela :
Code c:
struct MaStructure {
int var1 = 10;
long var2 = 40000;
double varN = 12.5;
};

Initialiser des variables directement dans la structure est interdit !


Il va donc falloir qu’on initialise cette structure dans une fonction de notre programme. Dans le main par exemple.
Pour cela il va nous falloir créer une variable de type MaStructure, car oui, en fait MaStructure est un type de variable.

Pour créer cette variable, il nous suffira juste de faire comme si il ne s’agissait que d’une simple variable, à la différence qu’on ajoute quand même le mot-clé struct pour bien signaler qu’on utilise une structure.
Voilà donc ce que ça nous donne :

Code c:
#include <stdio.h>
#include <stdlib.h>

struct MaStructure {
int var1;
long var2;
double varN;
};

int main()
{
struct MaStructure maStructure;
/* On a bien créer une variable de type MaStrcture se nommant maStrcture */

return EXIT_SUCCESS; /* Equivalent à return 0 sous Windows */
}



A noter qu’on peut assi déclarer des variables directement après la déclaration de la structure de cette manière :

Code c:
struct MaStructure {
int var1;
long var2;
double varN;
}var3;


On aura ici une variable globale, (= dont la portée s’étend à tout le programme) var3 de type MaStructure.

Cependant nos variables ne sont pas encore initialisées et leurs valeurs est donc aléatoires. Pour les mettre à 0, il suffit simplement de faire comme ceci :

Code c:
struct MaStructure maStructure = {};
}


Toutes les variables de la structure MaStructure sont donc initialisées à 0.

Pour en avoir le coeur net, nous allons voir comment accéder aux attributs d’une structure grâce à la variable maStructure que nous avons créer juste avant suivi d’un point (« . »), puis du nom de la variable contenue dans MaStructure à laquelle on souhaite accéder. De cette manière ci :

Code c:
struct MaStructure {
int var1;
long var2;
double varN;
}var3;

int main()
{
struct MaStructure maStructure = {};

printf(« %dn », maStructure.var1); /* Accès a var1 de MaStructure */
printf(« %ldn », maStructure.var2); /* Accès a var2 de MaStructure */
printf(« %lfn », maStructure.varN); /* Accès a varN de MaStructure */

return EXIT_SUCCESS;
}


Ainsi le code suivant nous affiche :

Code console:
0
0
0.000000


Nos variables sont donc bien initialisées à 0.

Maintenant si l’on souhaite définir les variables de MaStructure avec d’autres valeurs, il existe plusieurs manières :

Code c:
struct MaStructure maStructure = {10, 40000, 12.5};


avec cette méthode, on initialise les variables dans l’ordre. Si on en oublie (qu’on oublie le 12.5 de varN par exemple), les variables non initialisées seront mises à 0.

On peut aussi faire de cette méthode :

Code c:
struct MaStructure maStructure;
maStructure.var1 = 10;
maStructure.var2 = 40000;
maStructure.varN = 12.5;


Ainsi toutes les variables seront bien définis, par contre si là encore on oublie de déclarer une variable elles ne seront pas mises à zéro et auront une valeurs aléatoires. De plus si une des variables à déjà été définie alors sa valeur sera remplacée par la nouvelle.

On peut donc maintenant modifier n’importe quelles variables de MaStructure.

         2 – Pointeurs vers des Structures

    Il est aussi possible de créer, en langage C, des variables de types pointeurs vers structures. Pour cela rien de plus simple puisse qu’on peut en créer un comme n’importe quel pointeur d’un tout autre type.

Code c:
struct MaStructure *maStructure = NULL;


On crée donc donc ici un pointeur maStructure » de type MaStructure, qu’on initialise a NULL pour éviter une erreur.
Le principal atout d’un pointeur de strcutures c’est qu’il va nous permettre de modifier les attributs de notre structures depuis une autre fonction.
Ainsi pour envoyer notre structure dans une fonction, il va simplement falloir faire comme on le ferait avec un simple pointeur :

Code c:
struct MaStructure {
int var1;
long var2;
double varN;
}var3;

void fonction(struct MaStructure *maStructure);

/* Pensez bien à mettre le prototype après la déclaration de la strcture */

int main()
{
struct MaStructure maStructure;

fonction(&amp;maStructure);
/* On envoie l’adresse de maStrcture comme paramètre */

printf(« %dn », maStructure.var1);
printf(« %ldn », maStructure.var2);
printf(« %lfn », maStructure.varN);

return EXIT_SUCCESS;
}

void fonction(struct MaStructure *maStructure)
{
/* Ici on pourra modifier les attributs de MaStructure */
}


Cependant avant pour accéder aux attribut on faisait comme cela :

Code c:
maStructure.var1 = 10;


Mais avec un pointeur ça ne marche plus comme ça (ç’aurait été trop beau )
Il va nous falloir utiliser une notation un peu plus complexe :

Code c:
(*maStructure).var1 = 10;


Expliquons un peu tous ça. On utilise l’étoile pour bien montrer qu’on veut accéder à la variable et non à l’adresse contenue dans le pointeur. Enfin on met des parenthèses autour de ce pointeur pour signaler au « . » qu’il doit s’appliquer a *maStructure et non pas à maStructure. C’est assez obscure je le reconnais mais c’est essentiel.

Cependant les développeurs avant vous on aussi remarqué que cette notation n’était pas très évidente c’est pourquoi ils ont créé un symbole ( une flèche -> qui permet de palier à ce problème, ainsi au lieu de faire :

Code c:
(*maStructure).var1 = 10;


Nous ferrons :

Code c:
maStructure->var1 = 10;


C’est à dire que lorsque nous aurons à faire à un pointeur, il suffira juste de remplacer le point par le symbole de la flèche. Vous devriez donc maintenant être capable d’initialiser les attributs de notre structure :

Code c:
struct MaStructure {
int var1;
long var2;
double varN;
}var3;

void fonction(struct MaStructure *maStructure);

/* Pensez bien à mettre le prototype après la déclaration de la structure */

int main()
{
struct MaStructure maStructure;

fonction(&amp;maStructure);
/* On envoie l’adresse de maStrcture comme paramètre */

printf(« %dn », maStructure.var1);
printf(« %ldn », maStructure.var2);
printf(« %lfn », maStructure.varN);

return EXIT_SUCCESS;
}

void fonction(struct MaStructure *maStructure)
{
maStructure->var1 = 10;
maStructure->var2 = 40000;
maStructure->varN = 12.5;
}


Qui nous donne ceci :

Code console:
10
40000
12.500000


Dans la prochaine partie nous verrons le typedef, les énumérations et les unions.