NEO ::: TEAM
Vous souhaitez réagir à ce message ? Créez un compte en quelques clics ou connectez-vous pour continuer.

NEO ::: TEAM

New Evolution Owner
 
AccueilRechercherDernières imagesS'enregistrerConnexion
-50%
Le deal à ne pas rater :
Ampli Home Cinema Denon AVR-X1700H à 399€
399 € 799 €
Voir le deal

 

 Chapitre 3. Types avancés et classes de stockage

Aller en bas 
AuteurMessage
hou$$am
Fondateur
Fondateur
hou$$am


Nombre de messages : 386
Localisation : Tlemcen-Algeria
Date d'inscription : 04/01/2007

Chapitre 3. Types avancés et classes de stockage Empty
MessageSujet: Chapitre 3. Types avancés et classes de stockage   Chapitre 3. Types avancés et classes de stockage Icon_minitimeMar 9 Jan - 2:30

Le langage C/C++ permet la définition de types personnalisés construits à partir des types de base du langage. Outre les tableaux, que l'on a déjà présentés, il est possible de définir différents types de données évolués, principalement à l'aide de la notion de structure. Par ailleurs, les variables déclarées dans un programme se distinguent, outre par leur type, par ce que l'on appelle leur classe de stockage. La première section de ce chapitre traitera donc de la manière dont on peut créer et manipuler de nouveaux types de données en C/C++, et la deuxième section présentera les différentes classes de stockage existantes et leur signification précise.

Structures de données et types complexes

En dehors des types de variables simples, le C/C++ permet de créer des types plus complexes. Ces types comprennent essentiellement les structures, les unions et les énumérations, mais il est également possible de définir de nouveaux types à partir de ces types complexes.

3.1.1. Les structures
Les types complexes peuvent se construire à l'aide de structures. Pour cela, on utilise le mot clé struct. Sa syntaxe est la suivante :

Code:
struct [nom_structure]
{
    type champ;
  [type champ;
  [...]]
};

Il n'est pas nécessaire de donner un nom à la structure. La structure contient plusieurs autres variables, appelées champs. Leur type est donné dans la déclaration de la structure. Ce type peut être n'importe quel autre type, même une structure.

La structure ainsi définie peut alors être utilisée pour définir une variable dont le type est cette structure.

Pour cela, deux possibilités :


faire suivre la définition de la structure par l'identificateur de la variable ;

Exemple 3-1. Déclaration de variable de type structure

Code:
struct Client
{
    unsigned char Age;
    unsigned char Taille;
} Jean;
ou, plus simplement :


struct
{
    unsigned char Age;
    unsigned char Taille;
} Jean;


Dans le deuxième exemple, le nom de la structure n'est pas mis.

déclarer la structure en lui donnant un nom, puis déclarer les variables avec la syntaxe suivante :

Code:
[struct] nom_structure identificateur;

Exemple 3-2. Déclaration de structure

struct Client
{
    unsigned char Age;
    unsigned char Taille;
};

struct Client Jean, Philippe;
Client Christophe; // Valide en C++ mais invalide en C
Dans cet exemple, le nom de la structure doit être mis, car on utilise cette structure à la ligne suivante. Pour la déclaration des variables Jean et Philippe de type struct Client, le mot clé struct a été mis. Cela n'est pas nécessaire en C++, mais l'est en C. Le C++ permet donc de déclarer des variables de type structure exactement comme si le type structure était un type prédéfini du langage. La déclaration de la variable Christophe ci-dessus est invalide en C.


Les éléments d'une structure sont accédés par un point, suivi du nom du champ de la structure à accéder. Par exemple, l'âge de Jean est désigné par Jean.Age.

Note : Le typage du C++ est plus fort que celui du C, parce qu'il considère que deux types ne sont identiques que s'ils ont le même nom. Alors que le C considère que deux types qui ont la même structure sont des types identiques, le C++ les distingue. Cela peut être un inconvénient, car des programmes qui pouvaient être compilés en C ne le seront pas forcément par un compilateur C++. Considérons l'exemple suivant :


Code:
int main(void)
{
    struct st1
    {
        int a;
    } variable1 = {2};
    struct
    {
        int a;
    } variable2;    /* variable2 a exactement la même structure
                      que variable1, */
    variable2 = variable1;  /* mais cela est ILLÉGAL en C++ ! */
    return 0;
}


Bien que les deux variables aient exactement la même structure, elles sont de type différents ! En effet, variable1 est de type « st1 », et variable2 de type « » (la structure qui a permis de la construire n'a pas de nom). On ne peut donc pas faire l'affectation. Pourtant, ce programme était compilable en C pur...

Note : Il est possible de ne pas donner de nom à une structure lors de sa définition sans pour autant déclarer une variable. De telles structures anonymes ne sont utilisables que dans le cadre d'une structure incluse dans une autre structure :


Code:
struct struct_principale
{
    struct
    {
        int champ1;
    };
    int champ2;
};


Dans ce cas, les champs des structures imbriquées seront accédés comme s'il s'agissait de champs de la structure principale. La seule limitation est que, bien entendu, il n'y ait pas de conflit entre les noms des champs des structures imbriquées et ceux des champs de la structure principale. S'il y a conflit, il faut donner un nom à la structure imbriquée qui pose problème, en en faisant un vrai champ de la structure principale.

3.1.2. Les unions

Les unions constituent un autre type de structure. Elles sont déclarées avec le mot clé union, qui a la même syntaxe que struct. La différence entre les structures et les unions est que les différents champs d'une union occupent le même espace mémoire. On ne peut donc, à tout instant, n'utiliser qu'un des champs de l'union.

Exemple 3-3. Déclaration d'une union

Code:
union entier_ou_reel
{
    int entier;
    float reel;
};

union entier_ou_reel x;
x peut prendre l'aspect soit d'un entier, soit d'un réel. Par exemple :


Code:
x.entier=2;

affecte la valeur 2 à x.entier, ce qui détruit x.reel.

Si, à présent, on fait :


Code:
x.reel=6.546;

la valeur de x.entier est perdue, car le réel 6.546 a été stocké au même emplacement mémoire que l'entier x.entier.

Les unions, contrairement aux structures, sont assez peu utilisées, sauf en programmation système où l'on doit pouvoir interpréter des données de différentes manières selon le contexte. Dans ce cas, on aura avantage à utiliser des unions de structures anonymes et à accéder aux champs des structures, chaque structure permettant de manipuler les données selon une de leurs interprétations possibles.

Exemple 3-4. Union avec discriminant

Code:
struct SystemEvent
{
    int iEventType;  /* Discriminant de l'événement.
                        Permet de choisir comment l'interpréter. */
    union
    {
        struct
        {                    /* Structure permettant d'interpréter */
            int iMouseX;      /* les événements souris. */
            int iMouseY;
        };
        struct
        {                    /* Structure permettant d'interpréter */
            char cCharacter;  /* les événements clavier. */
            int iShiftState;
        };
        /* etc. */
    };
};

/* Exemple d'utilisation des événements : */
int ProcessEvent(struct SystemEvent e)
{
    int result;
    switch (e.iEventType)
    {
    case MOUSE_EVENT:
        /* Traitement de l'événement souris... */
        result = ProcessMouseEvent(e.iMouseX, e.iMouseY);
        break;
    case KEYBOARD_EVENT:
        /* Traitement de l'événement clavier... */
        result = ProcessKbdEvent(e.cCharacter, e.iShiftState);
        break;
    }
    return result;
}


3.1.3. Les énumérations

Les énumérations sont des types intégraux (c'est-à-dire qu'ils sont basés sur les entiers), pour lesquels chaque valeur dispose d'un nom unique. Leur utilisation permet de définir les constantes entières dans un programme et de les nommer. La syntaxe des énumérations est la suivante :

Code:
enum enumeration
{
    nom1 [=valeur1]
  [, nom2 [=valeur2]
  [...]]
};

Dans cette syntaxe, enumeration représente le nom de l'énumération et nom1, nom2, etc. représentent les noms des énumérés. Par défaut, les énumérés reçoivent les valeurs entières 0, 1, etc. sauf si une valeur explicite leur est donnée dans la déclaration de l'énumération. Dès qu'une valeur est donnée, le compteur de valeurs se synchronise avec cette valeur, si bien que l'énuméré suivant prendra pour valeur celle de l'énuméré précédent augmentée de 1.

Exemple 3-5. Déclaration d'une énumération

Code:
enum Nombre
{
    un=1, deux, trois, cinq=5, six, sept
};

Dans cet exemple, les énumérés prennent respectivement leurs valeurs. Comme quatre n'est pas défini, une resynchronisation a lieu lors de la définition de cinq.

Les énumérations suivent les mêmes règles que les structures et les unions en ce qui concerne la déclaration des variables : on doit répéter le mot clé enum en C, ce n'est pas nécessaire en C++.

3.1.4. Les champs de bits

Il est possible de définir des champs de bits et de donner des noms aux bits de ces champs. Pour cela, on utilisera le mot clé struct et on donnera le type des groupes de bits, leurs noms, et enfin leurs tailles :

Exemple 3-6. Déclaration d'un champs de bits

Code:
struct champ_de_bits
{
    int var1;                    /* Définit une variable classique. */
    int bits1a4  : 4;            /* Premier champ : 4 bits. */
    int bits5a10 : 6;            /* Deuxième champ : 6 bits. */
    unsigned int bits11a16 : 6;  /* Dernier champ : 6 bits. */
};

La taille d'un champ de bits ne doit pas excéder celle d'un entier. Pour aller au-delà, on créera un deuxième champ de bits. La manière dont les différents groupes de bits sont placés en mémoire dépend du compilateur et n'est pas normalisée.

Les différents bits ou groupes de bits seront tous accessibles comme des variables classiques d'une structure ou d'une union :


Code:
struct champ_de_bits essai;

int main(void)
{
    essai.bits1a4 = 3;
    /* suite du programme */
    return 0;
}
Revenir en haut Aller en bas
 
Chapitre 3. Types avancés et classes de stockage
Revenir en haut 
Page 1 sur 1
 Sujets similaires
-
» chapitre 3. /Les classes de stockage
» Chapitre 2. / La boucle for
» Chap 3. /Les alias de types
» Chapitre 2. / Le while

Permission de ce forum:Vous ne pouvez pas répondre aux sujets dans ce forum
NEO ::: TEAM :: Informatique :: Languages de programmation :: C++-
Sauter vers:  
Ne ratez plus aucun deal !
Abonnez-vous pour recevoir par notification une sélection des meilleurs deals chaque jour.
IgnorerAutoriser