Vous êtes sur la page 1sur 39

Programmation II

Module: M1 - LFSMI - S4

Prof. R. HANNANE
r.hannane@uca.ma

Faculté des Sciences Semlalia, Marrakech


Université Cadi Ayyad

Prof. R. HANNANE (FSSM) Programmation II 1 / 39


Les types composés

Les types composés

Prof. R. HANNANE (FSSM) Programmation II 2 / 39


Les types composés

Types composés
Introduction

A partir des types prédéfinis du langage C (caractères,


entiers, flottants), on peut créer de nouveaux types de
variables personnalisés (nos propres types de variables),
appelés types composés

Les types composés permettent de représenter des


ensembles de données organisées

Pourquoi faire?
⇒ Créer de nouveaux types de variables devient
indispensable quand on cherche à faire des
programmes plus complexes

Prof. R. HANNANE (FSSM) Programmation II 3 / 39


Les types composés

Types composés
Structure

Il est intéressant de faire associer plusieurs caractéristiques à


une variable

⇒ L’association de ces différentes caractéristiques devient


possible en définissant un nouveau type structure

Contrairement aux tableaux qui nous obligent à utiliser


le même type dans tout le tableau, on peut créer une
structure comportant des variables de types long, char,
int et double à la fois

Une structure permet de désigner sous un seul nom une


suite finie d’objets de types différents
Prof. R. HANNANE (FSSM) Programmation II 4 / 39
Les types composés

Structure
Définition d’une structure

Les structures sont généralement définies dans les fichiers


.h, au même titre donc que les prototypes et les define
Une définition de structure commence par le mot-clé struct,
suivi du NomDeStructure

struct NomDeS tructur e


{
int var1 ;
float var2 ;
double var3 ;
};

Attention:
Le point-virgule après l’accolade fermante est obligatoire.
Si vous ne le faites pas, la compilation plantera.
Prof. R. HANNANE (FSSM) Programmation II 5 / 39
Les types composés

Structure
Définition d’une structure
Remarque:
On met entre les accolades les variables dont est
composée notre structure
Une structure est généralement composée d’au moins deux
”sous-variables”
Il n’y a pas de limite au nombre de variables dans une structure
Exemple de définition d’une structure nommée Coordonnees qui
permette de stocker les coordonnées d’un point:
Exemple:
struct Coordonnees
{
int x ; // Abscisses
int y ; // Ordonn é es
};

Prof. R. HANNANE (FSSM) Programmation II 6 / 39


Les types composés

Structure
L’utilisation de structure

Une fois que la structure est définie dans le fichier .h, on peut
l’utiliser dans une fonction du fichier .c
La création d’une variable de type structure se fait comme suite:

Exemple:
# include " main . h " /* Inclusion du fichier . h qui contient
les prototypes et structures */
int main ()
{
struct Coordonnees point ; /* Cr é ation d ’ une variable " point "
de type Coordonnees . Cette variable est
a ut om at i qu em e nt compos é e de
deux sous - variables : x et y */
// suite du programme
return 0;
}

Prof. R. HANNANE (FSSM) Programmation II 7 / 39


Les types composés

Structure
L’utilisation de structure
Note:
Il est obligatoire d’écrire le mot-clé struct lors de la
déclaration de la variable
Cela permet au compilateur de différencier un type de
base (comme int) d’un type personnalisé (comme
Coordonnees)
Problème:
C’est lourd de mettre le mot struct à chaque définition
de variable personnalisée
Solution:
Ajout de l’instruction typedef qui sert à créer un alias de
structure, c’est-à-dire qu’écrire telle chose équivaut à écrire
telle autre chose
Prof. R. HANNANE (FSSM) Programmation II 8 / 39
Les types composés

Structure
L’utilisation de structure
Comment??
⇒ En ajoutant une ligne commençant par typedef juste avant
la définition de la structure
Exemple:
typedef struct Coordonnees Coordonnees ;
// é crire le mot Coordonnees est é quivalent à
é crire struct Coordonnees
struct Coordonnees
{
int x ;
int y ;
};

typedef: indique que nous allons créer un alias de structure


struct Coordonnees: c’est le nom de la structure dont nous
allons créer un alias (”équivalent”)
Coordonnees: c’est le nom de l’équivalent
Prof. R. HANNANE (FSSM) Programmation II 9 / 39
Les types composés

Structure
L’utilisation de structure
L’habitude veut que ces deux étapes soient faites en
même temps, comme suite:
Exemple:
typedef struct Coordonnees
{
int x ;
int y ;
} Coordonnees ;

Maintenant, pas besoin de mettre le mot struct à chaque


déclaration de variable de type Coordonnees
Exemple:
int main (){
Coordonnees point ; /* Le compilateur comprend qu ’ il s ’ agit
de " struct Coordonnees " gr a
^ ce au typedef */
...
return 0;}
Prof. R. HANNANE (FSSM) Programmation II 10 / 39
Les types composés

Structure
L’accès aux champs de structure

Chaque élément d’une structure, appelé membre ou champ, est désigné par un
identificateur

Chaque champ d’une structure peut être manipulé comme n’importe


quelle variable du type correspondant

Contrairement aux tableaux, les différents champ d’une structure


n’occupent pas nécessairement des zones contiguës en mémoire

Contrairement aux tableaux, l’accès à chaque champ de la structure se


fera, non plus par une indication de position, mais par son nom au sein de
la structure

On accède au membre d’une structure en faisant suivre le nom de la


variable structure par l’opérateur ”.” suivi du nom de champ tel qu’il a
été défini dans le modèle

Prof. R. HANNANE (FSSM) Programmation II 11 / 39


Les types composés

Structure
L’accès aux champs de structure

Exemple:
typedef struct Coordonnees
{
int x ;
int y ;
} Coordonnees ;
int main (){
Coordonnees point ;
point . x =12; /* affecte la valeur 12 au champ x
de la structure point */
printf ( " x =% d " , point . x ); /* affiche la valeur du
champ x de la structure point */
scanf ( " % d " ,& point . y ); /* lit une valeur qui sera
affect é e au champ y de la structure point .
Notez bien la pr é sence de l ’ op é rateur & */
point . x ++; /* incr é mente de 1 la valeur du
champ x de la structure point */
return 0;
}

Prof. R. HANNANE (FSSM) Programmation II 12 / 39


Les types composés

Structure
Utilisation globale d’une structure

Il est possible d’affecter à une structure le contenu


d’une structure définie à partir du même modèle

I Si les structures point1 et point2 ont été déclarées suivant le


modèle Coordonnees défini précédemment

Coordonnees point1 , point2 ;


point2 = point1 ;

I Une telle affectation globale remplace avantageusement :

point2 . x = point1 . x ;
point2 . y = point1 . y ;

Prof. R. HANNANE (FSSM) Programmation II 13 / 39


Les types composés

Structure
Utilisation globale d’une structure

Attention:
Une affectation globale n’est possible que si les structures
ont été définies avec le même nom de modèle

L’affectation globale n’est pas possible entre tableaux.


Elle l’est, par contre, entre structures

Il est possible, en créant artificiellement une structure


contenant un seul champ qui est un tableau, de réaliser une
affectation globale entre tableaux

Prof. R. HANNANE (FSSM) Programmation II 14 / 39


Les types composés

Structure
Initialisations de structure

En l’absence d’initialisation explicite, les structures de classe statique sont,


par défaut, initialisées à zéro ; celles possédant la classe automatique ne
sont pas initialisées par défaut (elles contiendront donc des valeurs aléatoires)
Exemple:
struct Coordonnees {
int x ;
int y ;
} p1 , p2 ;
int main (){
struct Coordonnees p3 ;
printf ( " p1 (% d , % d ) " , p1 .x , p1 . y ); /* p1 (0 ,0) */
printf ( " p2 (% d , % d ) " , p2 .x , p2 . y ); /* p2 (0 ,0) */
printf ( " p3 (% d , % d ) " , p3 .x , p3 . y ); /* p3 (13765487 ,145729297) */
return 0;
}

p1 et p2 sont des variables globales initialisées automatquement à 0


p3 est une variable locale initialisée aléatoirement

Prof. R. HANNANE (FSSM) Programmation II 15 / 39


Les types composés

Structure
Initialisations de structure

Il est possible d’initialiser explicitement une structure lors


de sa déclaration
La description des différents champs se présente sous la forme
d’une liste de valeurs séparées par des virgules, chaque
valeur étant une constante ayant le type du champ
correspondant.
Aussi, il est possible d’omettre certaines valeurs
Exemple:
struct Coordonnees p1 ={12 ,20} , p2 ={2} , p3 ={} , p4 ={. y =3 ,. x =7};
printf ( " p1 (% d , % d ) " , p1 .x , p1 . y ); // p1 (12 ,20)
printf ( " p2 (% d , % d ) " , p2 .x , p2 . y ); // p2 (2 ,0)
printf ( " p3 (% d , % d ) " , p3 .x , p3 . y ); // p3 (0 ,0)
printf ( " p4 (% d , % d ) " , p4 .x , p4 . y ); // p4 (7 ,3)

Prof. R. HANNANE (FSSM) Programmation II 16 / 39


Les types composés

Structure
Structure et tableaux

Les structures peuvent contenir des tableaux


⇒ On peut donc placer des tableaux de char(chaı̂nes de
caractères)
Exemple d’une structure Personne qui stocke diverses
informations sur une personne :

Exemple:
struct Personne
{
char nom [100];
char prenom [100];
char adresse [1000];
int age ;
char genre ; // h = homme , f = femme
};

Prof. R. HANNANE (FSSM) Programmation II 17 / 39


Les types composés

Structure
Structure et tableaux

Attention aux notations suivantes:


struct Personne employe ;
employe . nom [0];

représente le premier caractère du champ nom de la structure


employe
& employe . nom [9];

représente l’adresse du 10eme caractère du champ nom de la


structure employe
employe . nom ;

représente le champ nom de la structure employe , c-a-d


l’adresse de ce tableau
Prof. R. HANNANE (FSSM) Programmation II 18 / 39
Les types composés

Structure
Structure et tableaux

La structure Personne pourrait servir à représenter une liste


des employes d’une entreprise, employe qui serait défini par
son nom (caractère) et ses champs

Notez bien que Personne est un nom de modèle de structure,


tandis que employe ça va représenter un tableau de n éléments
du type Personne

Prof. R. HANNANE (FSSM) Programmation II 19 / 39


Les types composés

Structure
Structure et tableaux
Attention aux Tableaux de structure
struct Personne employe [10];
employe [ i ]. nom ;

représente le nom de l’employe de rang i du tableau employe


⇒ Il s’agit donc d’une valeur de type tableau de char
employe [4];

représente la structure de type Personne correspondant au


cinquième élément du tableau employe
Exemple d’initialisation (partielle) de la variable employe lors de
sa déclaration:
struct Personne emplye [10]= {
{ " Ahmadi " , " Anas " , " B .10 cite Dakhla , Agadir " , 35 , 1} ,
{ " Mesrar " ," Rim " ," B .3 , AinChkef , Fes " , 32 , 0}
};
Prof. R. HANNANE (FSSM) Programmation II 20 / 39
Les types composés

Structure
Structure de structures

Les champs d’une structure peuvent aussi être une


varibale de type structure

Exemple:
struct date
{
int jour ;
int mois ;
int annee ;
};

struct Personne
{
char nom [50] ;
char prenom [50] ;
int age ;
struct date date_embauche ;
} employe , employe1 ;

Prof. R. HANNANE (FSSM) Programmation II 21 / 39


Les types composés

Structure
Structure de structures

Attention aux notations suivantes:


employe . date_embauche . annee ;

représente l’année d’embauche correspondant à la structure


employe. ⇒Il s’agit d’une valeur de type int
employe . date_embauche ;

représente la date d’embauche correspondant à la structure


employe. ⇒Il s’agit cette fois d’une structure de type date
Elle pourra éventuellement faire l’objet d’affectations globales
employe1 . date_embauche = employe . date_embauche ;

Prof. R. HANNANE (FSSM) Programmation II 22 / 39


Les types composés

Structure
Structure et fonctions
Les structures peuvent être utilisées comme résultat
d’une fonction
Exemple: La fonction creationpoint qui prend deux entiers
et retourne une structure point

Exemple:
struct Coordonnees creationpoint ( int x , int y ) {
struct Coordonnees temp ;
temp . x = x ;
temp . y = y ;
return temp ;
}

Attention: il ne faut pas confondre la variable x fournie en


argument avec celle qui est membre de la structure temp (de
même pour la variable y )
Prof. R. HANNANE (FSSM) Programmation II 23 / 39
Les types composés

Structure
Structure et fonctions

Les structures peuvent aussi être transmise comme des


arguments d’une fonction

Trois possibilités pour le passage des structures aux


functions:

o Passer la structure entière

o Passer les champs (membres) séparement

o Passer un pointeur sur la structure

Prof. R. HANNANE (FSSM) Programmation II 24 / 39


Les types composés

Structure
Structure et fonctions

Naturellement, les valeurs de la structure x sont recopiées localement dans la


fonction fct lors de son appel ; les modifications de s au sein de fct n’ont aucune
incidence sur les valeurs de x
Exemple:
# include < stdio .h >
typedef struct enreg {
int a ;
int b ; } Enreg ;
int main () {
void fct ( Enreg ) ;
Enreg x ;
x . a = 1; x . b = 12;
printf ( " \ n avant appel fct : % d % d " ,x .a , x . b );
fct ( x ) ;
printf ( " \ n au retour dans main : % d % d " , x .a , x . b );
return 0;
}
void fct ( Enreg s )
{
s . a = 0; s . b =1;
printf ( " \ n dans fct : % d % d " , s .a , s . b );
} /* Affichage :
avant appel fct : 1 12
dans fct : 0 1
au retour dans main : 1 12
*/

Prof. R. HANNANE (FSSM) Programmation II 25 / 39


Les types composés

Structure
Structure et pointeurs

Une fonction fct peut reçoit effectivement l’adresse


d’une structure et non plus sa valeur

L’appel de fct devra donc se présenter sous la forme


fct (& x ) ;

⇒ Cela signifie que son en-tête sera de la forme:


void fct ( struct enreg * ads ) ;

Problème:
L’opérateur ” . ” ne convient plus lorsqu’on veut accéder,
au sein de la définition de fct, à chacun des champs de la
structure d’adresse ads, car il suppose comme premier
opérande un nom de structure et non une adresse
Prof. R. HANNANE (FSSM) Programmation II 26 / 39
Les types composés

Structure
Structure et pointeurs

Solutions:
1 Adopter une notation telle que (*ads).a ou (*ads).b pour
désigner les champs de la structure d’adresse ads

2 Faire appel à un nouvel opérateur noté ->, lequel permet


d’accéder aux différents champs d’une structure à partir
de son adresse de début

⇒ Ainsi, au sein de fct, la notation ads->b désignera le second


champ de la structure reçue en argument ; elle sera équivalente à
(*ads).b

Prof. R. HANNANE (FSSM) Programmation II 27 / 39


Les types composés

Structure
Structure et pointeurs
Exemple:
# include < stdio .h >
typedef struct enreg {
int a ;
int b ; } Enreg ;
int main () {
void fct ( Enreg *) ;
Enreg x ;
x . a = 1; x . b = 12;
printf ( " \ n avant appel fct : % d % d " ,x .a , x . b );
fct (& x ) ;
printf ( " \ n au retour dans main : % d % d " , x .a , x . b );
return 0;}
void fct ( Enreg * s ){
s - > a = 0; // (* s ). a =0;
s - > b =1; // (* s ). b =1;
printf ( " \ n dans fct : % d % d " , s - >a , s - > b );
} /* Affichage :
avant appel fct : 1 12
dans fct : 0 1
au retour dans main : 0 1 */
Prof. R. HANNANE (FSSM) Programmation II 28 / 39
Les types composés

Structure
Structure et pointeurs
Attention:
Le raccourci de la flèche (”− >”) est réservée aux
pointeurs, tandis que le point (” . ”) est réservé aux
variables
Exemple:
int main ()
{
Coordonnees point ;
Coordonnees * pointeurPoint = & point ;
point . x = 10; /* On travaille sur une variable ,
on utilise le "." */
printf ( " point . x =% d \ n " , point . x ); // point . x =10
pointeurPoint - > x = 12; /* On travaille sur un
pointeur , on utilise la fl è che */
printf ( " pointeurPoint - > x =% d \ n " , pointeurPoint - > x );
// pointeurPoint - > x =12
return 0;
}
Prof. R. HANNANE (FSSM) Programmation II 29 / 39
Les types composés

Structure
Structure et Allocation Dynamique
Les champs d’une structure peuvent aussi être des pointeurs
Exemple:
# include < stdio .h >
# include < stdlib .h >
typedef struct data {
int * array ;
} Data ;
int main (){
int j , l =2;
Data x , y ;
x . array =( int *) malloc ( l * sizeof ( int ));
y . array =( int *) malloc ( l * sizeof ( int ));
x . array [0]=1; x . array [1]=2;
y . array [0]=8; y . array [1]=8;
for ( int j =0; j < l ; j ++)
printf ( " x . array [% d ]= % d \ t y . array [% d ]= % d \ n " ,j , x . array [ j ] ,j , y . array [ j ]);
x = y ; /* Attention : c ’ est pas une copie de contenu de memoire , mais c ’ est une
copie de pointeur d ’ array */
printf ( " \ n " );
for ( int j =0; j < l ; j ++)
printf ( " x . array [% d ]= % d \ t y . array [% d ]= % d \ n " ,j , x . array [ j ] ,j , y . array [ j ]);
x . array [0]=123;
printf ( " \ n \ n " );
for ( int j =0; j < l ; j ++)
printf ( " x . array [% d ]= % d \ t y . array [% d ]= % d \ n " ,j , x . array [ j ] ,j , y . array [ j ]);
free ( x . array );
return 0;}
Prof. R. HANNANE (FSSM) Programmation II 30 / 39
Les types composés

Structure
Structure et Allocation Dynamique

Exemple: (suite)

/* Affichage :
x . array [0]= 1 y . array [0]= 8
x . array [1]= 2 y . array [1]= 8

x . array [0]= 8 y . array [0]= 8


x . array [1]= 8 y . array [1]= 8

x . array [0]= 123 y . array [0]= 123


x . array [1]= 8 y . array [1]= 8
*/

Prof. R. HANNANE (FSSM) Programmation II 31 / 39


Les types composés

Structure
Structure et Allocation Dynamique
Exemple:
struct Coordonnees {
int x ;
int y ;
};
int main (){
int j , l =2;
struct Coordonnees * cord1 ;
cord1 = malloc ( l * sizeof ( struct Coordonnees ));
cord1 [0]. x =1;
cord1 [0]. y =1;
(*( cord1 +1)). x =2;
( cord1 +1) - > y =2; // cord1 [1]. y =3
printf ( " \n - - les Cordonnees - -\ n " );
for ( j =0; j < l ; j ++)
printf ( " P % d (% d , % d )\ n " ,j , cord1 [ j ]. x , cord1 [ j ]. y );
printf ( " \ n \n - - les Cordonnees - -\ n " );
l =3;
cord1 = realloc ( cord1 , l * sizeof ( struct Coordonnees ));
cord1 [2]. x =3;
cord1 [2]. y =3;
for ( j =0; j < l ; j ++)
printf ( " P % d (% d ,% d )\ n " ,j , cord1 [ j ]. x , cord1 [ j ]. y );
printf ( " \ n \ n " );
free ( cord1 );
return 0;}
Prof. R. HANNANE (FSSM) Programmation II 32 / 39
Les types composés

Structure
Structure et Allocation Dynamique

Exemple: (suite)
/* Affichage :
-- les Cordonnees - -
P0 (1 , 1)
P1 (2 , 2)

-- les Cordonnees - -
P0 (1 ,1)
P1 (2 ,2)
P2 (3 ,3)
*/

Et si struct Cordonnees contient un autre champ pointeur???

Exemple:
struct Coordonnees {
int x ;
int y ;
char * description ;
};

Prof. R. HANNANE (FSSM) Programmation II 33 / 39


Les types composés

Structure
Structure et Allocation Dynamique
Exemple:
int main (){
int j , l =2;
struct Coordonnees * cord1 ;
cord1 = malloc ( l * sizeof ( struct Coordonnees ));

cord1 [0]. x =1;


cord1 [0]. y =1;
cord1 [0]. description = malloc (20* sizeof ( char ));
strcpy ( cord1 [0]. description , " cordonee1 " );

cord1 [1]. x =2;


cord1 [1]. y =2
cord1 [1]. description = malloc (20* sizeof ( char ));
strcpy ( cord1 [1]. description , " cordonee2 " );

printf ( " \n - - les Cordonnees - -\ n " );


for ( j =0; j < l ; j ++)
printf ( " P % d (% d , % d )\ t description : % s \ n " ,
j , cord1 [ j ]. x , cord1 [ j ]. y , cord1 [ j ]. description );

for ( j =0; j < l ; j ++)


free ( cord1 [ j ]. description );
free ( cord1 ); /* ne libere pas la memoire entierement ,
il faut penser a liberer avec une boucle */
return 0;}
Prof. R. HANNANE (FSSM) Programmation II 34 / 39
Les types composés

Structure
Structure et l’effet de bourage (padding)
On peut savoir la taille d’une structure par sizeof()
Exemple:
...
struct Coordonnees {
char a ;
int x ;
char y ;
};
int main (){
...
printf ( " sizeof ( struct Coordonnees )=% ld \ n " ,
sizeof ( struct Coordonnees ));
printf ( " sizeof ( int )=% ld \ n " , sizeof ( int ));
...
return 0;}
/* Affichage :
sizeof ( struct Coordonnees )=12
sizeof ( int )=4
*/

Prof. R. HANNANE (FSSM) Programmation II 35 / 39


Les types composés

Structure
Structure et l’effet de bourage (padding)

Et si on change l’order des champs de notre structure??


Exemple:
...
struct Coordonnees {

char a ;
char y ;
int x ;
};
int main (){
...
printf ( " sizeof ( struct Coordonnees )=% ld \ n " ,
sizeof ( struct Coordonnees ));
...
return 0;}
/* Affichage :
sizeof ( struct Coordonnees )=8
*/

⇒ Que ce passe-il???
Prof. R. HANNANE (FSSM) Programmation II 36 / 39
Les types composés

Structure
Structure et effet de bourage (padding)

Attention:
CPU lit la mémoire mot par mot et non octet par octet, donc
l’ordre des champs dans la structure est très important.

Pour optimiser la performance, CPU


ajoute un rembourrage (padding) pour réduire le nombre de cycles
nécessaires pour lire les données.

Il est recommandé de déclarer les membres de la structure du plus


grand au plus petit pour optimiser la performance.
Exemple:
struct Coordonnees {
int x ;
char a ;
char y ;
};

Prof. R. HANNANE (FSSM) Programmation II 37 / 39


Les types composés

Structure
Structure et effet de bourage (padding)

Remarques:
Pour économiser de la mémoire, notamment en programmation
embarquée ou en programmation réseau, pensez à :
⇒ Utiliser la directive #pragma pack(1)

Exemple:
# include < stdio .h >
...
# pragma pack (1)
....
int main (){
...
printf ( " sizeof ( struct Coordonnees )=% ld \ n " , sizeof ( struct Coordonnees ));
...
return 0;}
/* Affichage :
sizeof ( struct Coordonnees )=6
*/

Prof. R. HANNANE (FSSM) Programmation II 38 / 39


Les types composés

Structure
Structure et effet de bourage (padding)

Remarques:
⇒ Ou bien ajouter à la fin de déclaration de la structure :
attribute ((packed))
Exemple:
...
struct Coordonnees {
char a ;
int x ;
char y ;
} __attribute__ (( packed ));
...
int main (){
...
printf ( " sizeof ( struct Coordonnees )=% ld \ n " , sizeof ( struct Coordonnees ));
...
return 0;}
/* Affichage :
sizeof ( struct Coordonnees )=6
*/
Prof. R. HANNANE (FSSM) Programmation II 39 / 39

Vous aimerez peut-être aussi