Les types structures et les pointeurs

Transcription

Les types structures et les pointeurs
L1 Informatique – Université Paris 8 - 2010-2011
Programmation Impérative I
Rim Chaabane [email protected]
- Cours 5 -
Les types structures et les pointeurs
1. Les types structures
Les objets de type structure est comme un tableau, constitué de la réunion d’un ensemble de
valeurs. Mais à la différence des tableaux, ces valeurs ne sont pas nécessairement de même type.
L’accès à une valeur de la structure ne se fait pas avec l’aide d’indice, mais grâce à son nom.
Le type structure permet de rassembler des informations sous une type que vous aurez créé. Par
exemple vous créez le type Personne qui possède un nom, un prénom et un âge. Ou bien un type
Point qui a une abscisse x et une ordonnée y.
1.1. Déclaration de structure
Pour définir un type structure personne, composée de trois champs : nom, prenom et age, il suffit
d’écrire les instructions suivantes :
/* définition du type struct personne */
struct personne {
char nom[20], prenom[15];
int age ;
} ;
Attention : le point-virgule est nécessaire après l'accolade fermante de la déclaration de la
structure.
- Personne est le nom du type créé
- Nom, prenom et age sont les champs de ce type
Nous utilisons ensuite ce type pour déclarer des variables :
/*déclaration de variables mere et père de type struct personne */
struct personne mere;
struct personne pere;
/* définition du type struct point */
struct point { float x, y ;
} ;
- point est le nom du type créé
- x et y sont les champs de ce type
/*déclaration de variables A et B de type struct point */
struct point A ;
struct point B ;
1
L1 Informatique – Université Paris 8 - 2010-2011
Programmation Impérative I
Rim Chaabane [email protected]
- Cours 5 -
La définition d’un type structure ne peut être précédé du mot clé const. Il faut considérer la
définition d’un type struct comme si vous définissez un nouveau type en C. Tout type en C ne
peut être constant. Par contre une donnée d’un type quelconque peut être déclarée comme
constante. Ainsi, il est autorisé de déclarer des valeurs de type struct comme constantes. Par
exemple :
const struct point A ;

Le type des champs d’une structure :
Les champs d’une structure peuvent être :
- de n’importe quel type de base
- des tableaux d’éléments de type quelconque
- des pointeurs
- des structures /!\ une structure peut comporter de champs de son type mais il faut le
déclarer au préalable de cette façon :
typedef struct personne pers ; /* pers est de type struct personne */
struct personne {
char nom[20], prenom[15];
int age ;
pers * pere ;
};

Déclaration de variable de type structure :
Il existe trois manières de déclarer des variables de type structure en C :
Première méthode
Deuxième méthode
Troisième méthode
struct personne{
char nom[20];
char prenom[20];
int no_employe;
};
struct {
char nom[20];
char prenom[20];
int no_employe;
} p1,p2;
struct{
char nom[20];
char prenom[20];
int no_employe;
} p3;
struct personne{
char nom[20];
char prenom[20];
int no_employe;
} p1,p2;
struct personne p1,p2;
p1=p2 ; /* OK */
struct personne p3;
p3 = p1 ; /* NOK */
p3 = p1 ; /* OK */
La première méthode, définit un type structure dont le nom est personne. Cette structure
contient trois champs : un tableau de caractères pour le champ nom, un tableau de caractères
pour le champ prenom et un entier pour le champ no_employe.
Plus loin de cette déclaration, nous déclarons deux variables p1 et p2 de type struct
personne.
Avec cette méthode, il est possible d’affecter à p1 la valeur de p2, ces deux variables étant
reconnues comme étant du même type.
2
L1 Informatique – Université Paris 8 - 2010-2011
Programmation Impérative I
Rim Chaabane [email protected]
- Cours 5 -
La deuxième méthode définit le même type de structure, sauf que cette fois-ci la structure ne
porte pas de nom et est immédiatement suivie des noms de variables p1 et p2 de ce type
structure. Si plus loin on écrit la même définition du type de structure (sans nom) suivi d’un nom
de variable p3, alors il nous sera possible d’effectuer des opérations entre p1 ou p2 et p3.
La troisième méthode définit un type structure avec le nom personne suivi immédiatement des
noms de variables p1 et p2. Dans cas si l’on crée comme à la méthode 1, une troisième variable
p3 de type struct personne, il nous sera impossible d’effectuer une quelconque opération
entre p1 ou p2 et p3. Ce dernier n’étant pas reconnu comme étant du même type que p1 et p2.
De ces trois méthodes c'est la première qui est recommandée, car elle permet de bien séparer la
définition du type structure de ses utilisations.
1.2.
Représentation en mémoire
La norme impose aux objets de type structure les deux contraintes suivantes :
- les champs doivent être alloués selon leur ordre d’apparition dans la structure ;
- l’adresse d’une structure correspond à l’adresse de son premier champ.
Ainsi dans les définitions suivantes, l’ordre d’apparition des champs est le même :
struct s1 {
int n, p ;
float x, y ;
};
struct s2 {
int n ;
int p ;
float x ;
float y;
};
struct s1 test ;
@m
n
1.3.
@m+1
p
@m+2
x
@m+3
y
test
Initialisation
Il existe deux méthodes pour initialiser une variable de type structure :
 Première méthode : l’initialisation se fait juste au moment de la déclaration de la variable
de type structure.
 Deuxième méthode : l’initialisation se fait après la déclaration de la variable de type
structure.
struct personne{
char nom[20];
char prenom[20];
int no_employe;
};
struct personne p1 = {"Dupond", "Jean", 7845}; /* méthode 1 */
struct personne p2 ;
3
L1 Informatique – Université Paris 8 - 2010-2011
Programmation Impérative I
Rim Chaabane [email protected]
- Cours 5 -
p2.nom = " Dupond";
p2.prenom = "Jean" ;
p2.no_employe = 7845 ;
/* méthode 2 */
Pour accéder aux champs de la variable p2, il suffit de faire suivre le nom de la variable d’un point
suivi du nom du champ.

Nous déclarons et initialisons maintenant un tableau de 3 éléments de type struct
personne :
- Avec la méthode 1 :
struct personne tab[3] = { {"Dupond", "Jean", 7845},
{"Le Notre", "Alfred", 4321},
{"Le Gall", "Marc", 5678}} ;
- Ou bien nous l’initialisons avec la méthode 2 :
struct personne tab[3] ;
tab[0].nom = "Dupond";
tab[0].prenom = "Jean";
tab[0].no_employe = 7845;
tab[1].nom = "Le Notre";
tab[1].prenom = "Alfred";
tab[1].no_employe = 1234;
tab[2].nom = "Le Gall";
tab[2].prenom = "Marc";
tab[2].no_employe = 5678;
Nous pouvons, alors noter qu’il est plus simple d’initialiser un tableau de structures avec la
première méthode. La seconde méthode est plutôt préconisée dans le cas ou les données du
tableau ne sont pas connues en début de programme. Exemple : le programme lit les données du
tableau de structures à partir d’un fichier de données.
Pour initialiser une variable de type structure, il n’est pas nécessaire de renseigner tous les champs
de la structure. Par exemple :
struct personne tab[3] = { {"Dupond", "Jean", 7845}, /* Correct */
{"Le Notre",}, /* Correct */
/* le troisième élément du
tableau n’apparait pas mais
étant donné que c’est le dernier
son absence ne gêne pas la
compilation */
};
Il est également possible d’affecter une valeur de structure à une autre, exemple :
struct personne p1, p2 = {"Dupond", "Jean", 7845};
p1=p2 ;
1.4.
Exemple d’utilisation
4
L1 Informatique – Université Paris 8 - 2010-2011
Programmation Impérative I
Rim Chaabane [email protected]
- Cours 5 -
2. Introduction à la notion de pointeur
Les pointeurs permettent de manipuler directement les adresses mémoire des objets crées ; tels
que les variables, les pointeurs ou encore les structures.
Soit les déclarations suivantes :
int n, t[5] ;
n est une variable de type int et t est un tableau de 5 éléments de type int.
Pour obtenir l’adresse de la variable n ou du tableau t il suffit de faire précéder le nom de
l’objet par un & :
&n ;
&t ;
Un pointeur en C contient l’adresse mémoire d’un objet. Pour déclarer par exemple un pointeur
sur l’adresse mémoire de la variable n il suffit d’écrire :
int *pn ; /* on dit que pn est le pointeur sur un objet de type int */
ou
int * pn ;
Il peut donc aussi bien contenir l’adresse de la variable n (qui est destinée à contenir un int)
que l’adresse d’un élément du tableau t comme par exemple &t[2]:
pn = &n ;
ou
5
L1 Informatique – Université Paris 8 - 2010-2011
Programmation Impérative I
Rim Chaabane [email protected]
- Cours 5 -
pn=&t[2] ;
Nous initialisons donc de cette façon une variable de type pointeur avec des adresses mémoire
d’objets de types int.
Pour accéder au contenu d’une adresse mémoire, il faut faire appel au pointeur précédé d’une
étoile comme ci-dessous :
*pn = 20 ; /* on place l’entier 20 dans l’adresse mémoire contenue dans pn */
Instruction C
description
Valeur
contenue
dans @m
int n = 3;
Réserve une adresse
mémoire @m qui
contient l’entier 3.
Déclare un pointeur pn
sur un entier.
Initialise le pointeur pn
à l’adresse de n.
La variable l prend
comme
valeur
le
contenu de l’adresse
pointée par pn.
L’adresse pointée par
pn
contient
maintenant la valeur 9.
Affiche le contenu de
@m
3
int * pn ;
pn = &n ;
int l = *pn ;
*pn = 9 ;
printf("%d\n",
*pn) ;

Résultat
3
3
pn = @m
3
l = 3
9
pn = @m
n = 9
*(@m)= 9
9
9
Affectation de pointeur :
p=NULL ;
//on crée un pointeur vide qui ne contient aucune adresse
mémoire
p = q ;
//p et q pointent sur le même objet
*p = *q ;
//l’adresse pointée par p contiendra l’objet pointé par q
if (p==q) {…} // si p et q pointent sur le même objet…
if (p !=q) {…} //si p et q ne pointent pas sur le même objet…
p+1 ;
//pointe sur l’objet suivant de type t (idem pour p++).
p-q ;
//retourne le nombre d’objets de type pointé entre les
adresses pointées par p et q.
6