Quels types de données existent dans le langage C. Variables en langage C. Déclarer une variable en C

Dans cette leçon, vous apprendrez Alphabet du langage C++, et aussi quoi Types de données le programme peut le traiter. Ce n'est peut-être pas le moment le plus excitant, mais cette connaissance est nécessaire ! De plus, lorsque vous commencerez à apprendre un autre langage de programmation, vous traverserez une étape d'apprentissage similaire avec plus de confiance. Un programme C++ peut contenir les symboles suivants :

  • Lettres latines majuscules et minuscules A, B, C..., x, y, z et trait de soulignement ;
  • Chiffres arabes de 0 à 9 ;
  • caractères spéciaux : ( ) , | , () + - / % * . \‘ : ?< > = ! & # ~ ; ^
  • caractères d'espacement, de tabulation et d'échappement nouvelle ligne.

Dans les tests de programme, vous pouvez utiliser commentaires. Si le texte contient deux barres obliques // et se termine par un caractère de nouvelle ligne ou est placé entre les caractères /* et */, alors le compilateur l'ignore.

Données en C++

Pour résoudre un problème, tout programme traite certaines données. Ils peuvent être divers types: nombres entiers et réels, caractères, chaînes, tableaux. En C++, les données sont généralement décrites au début de la fonction. À types de données de base les langues comprennent :

Pour générer d'autres types de données, de base et dites prescripteurs. C++ définit quatre spécificateurs de types de données :

  • court - court;
  • long - long ;
  • signé - signé;
  • non signé - non signé.

Type entier

Type de variable int dans la mémoire de l'ordinateur peut occuper 2 ou 4 octets. Cela dépend de la taille des bits du processeur. Par défaut, tous les types entiers sont considérés comme signés, c'est-à-dire le spécificateur signé ne peut pas être précisé. Spécificateur non signé vous permet de représenter uniquement des nombres positifs. Vous trouverez ci-dessous quelques plages de valeurs de type entier

Taper Gamme Taille
int -2147483648…2147483647 4 octets
entier non signé 0…4294967295 4 octets
signé en entier -2147483648…2147483647 4 octets
entier court -32768…32767 2 octets
long int -2147483648…2147483647 4 octets
entier court non signé 0…65535 2 octets

Type réel

Un nombre à virgule flottante est représenté sous la forme mE +- p, où m est la mantisse (nombre entier ou fractionnaire avec une virgule décimale), p est l'exposant (entier). Généralement des valeurs comme flotter prend 4 octets, et double 8 octets. Tableau des plages de valeurs réelles :

flotter 3,4E-38…3,4E+38 4 octets
double 1,7E-308…1,7E+308 8 octets
longue double 3.4E-4932…3.4E+4932 8 octets

Type booléen

Type de variable bouffon ne peut prendre que deux valeurs vrai ( vrai ) ou fasle ( mensonge ). Toute valeur non égale à zéro est interprétée comme vrai. Signification FAUX représenté en mémoire par 0.

tapez vide

L'ensemble de valeurs de ce type est vide. Il est utilisé pour définir des fonctions qui ne renvoient pas de valeur, pour indiquer liste vide arguments de fonction, comme type de base pour les pointeurs et dans les opérations de transtypage.

Conversion de types de données

En C++, il existe deux types de conversion de types de données : explicite et implicite.

  • Conversion implicite se produit automatiquement. Cela se fait lors de la comparaison, de l'affectation ou de l'évaluation d'expressions de différents types. Par exemple, le programme suivant imprimera sur la console une valeur telle que flotter

#include "stdafx.h" #include en utilisant l'espace de noms std ; int main() ( int i=5; float f=10.12; cout<>void"); renvoie 0; )

#include "stdafx.h"

#inclure

en utilisant l'espace de noms std ;

int main()

int je = 5 ; flotteur f = 10,12 ;

cout<< i / f ;

système ("pause>>void" ) ;

renvoie 0 ;

La priorité la plus élevée est donnée au type dans lequel le moins d'informations est perdue. Vous ne devez pas abuser de la conversion de type implicite, car diverses situations imprévues peuvent survenir.

  • Conversion explicite contrairement à l'implicite, elle est réalisée par le programmeur. Il existe plusieurs façons d'effectuer cette conversion :
  1. Conversion en styles C: (flotter) un
  2. Conversion en styles C++: flotter()

La conversion de type peut également être effectuée à l'aide des opérations suivantes :

static_cast<>()const_cast<>() réinterpréter_cast<>() dynamique_cast<> ()

static_cast<> ()

const_cast<> ()

réinterpréter_cast<> ()

dynamique_cast<> ()

statique_cas- convertit les types de données associés. Cet opérateur convertit les types selon les règles habituelles, ce qui peut être nécessaire lorsque le compilateur n'effectue pas de conversion automatique. La syntaxe ressemblera à ceci :

Tapez static_cast<Тип>(un objet);

En utilisant static_cast, vous ne pouvez pas supprimer la constance d'une variable, mais l'opérateur suivant peut le faire. const_cast- n'est utilisé que lorsqu'il est nécessaire de supprimer la constance d'un objet. La syntaxe ressemblera à ceci :

Taperconst_cast< Taper> (un objet);

réinterpréter_cast- utilisé pour la conversion différents types, des entiers vers un pointeur et vice versa. Si vous voyez un nouveau mot « index », ne vous inquiétez pas ! Il s’agit également d’un type de données, mais nous ne travaillerons pas avec lui de sitôt. La syntaxe ici est la même que celle des opérateurs évoqués précédemment :

Taperréinterpréter_casting< Taper> (un objet);

dynamique_cast- est utilisé pour conversion dynamique types, implémente la conversion de pointeurs ou de références. Syntaxe:

Taperdynamique _casting< Taper> (un objet);

Caractères de contrôle

Vous connaissez déjà certains de ces « caractères de contrôle » (par exemple, avec \n). Ils commencent tous par une barre oblique inverse et sont également entourés de guillemets doubles.

Image

Code hexadécimal

Nom

Son du bipeur

Revenir en arrière

Traduction de la page (format)

Traduction de ligne

Retour en calèche

Tabulation horizontale

Onglet vertical

Une différence importante entre le langage SI et les autres langages (PL1, FORTRAN, etc.) est l'absence de principe par défaut, ce qui conduit à la nécessité de déclarer explicitement toutes les variables utilisées dans le programme avec une indication de leurs types correspondants. .

Les déclarations de variables ont le format suivant :

[memory-class-specifier] descripteur de type-spécificateur [=initiateur] [,descripteur [= initiateur] ]...

Un descripteur est un identifiant pour une variable simple ou une construction plus complexe avec des crochets, des parenthèses ou un astérisque (un ensemble d'astérisques).

Un spécificateur de type est un ou plusieurs mots-clés qui définissent le type de la variable déclarée. Le langage SI dispose d'un ensemble standard de types de données, à l'aide duquel vous pouvez créer de nouveaux types de données (uniques).

Initiateur - spécifie la valeur initiale ou la liste des valeurs initiales attribuées à la variable lors de sa déclaration.

Spécificateur de classe de mémoire - déterminé par l'un des quatre mots-clés SI : auto, extern, register, static, et indique comment la mémoire sera allouée à la variable déclarée, d'une part, et, d'autre part, la portée de cette variable, c'est-à-dire à partir de quelles parties du programme il est accessible.

1.2.1 Catégories de types de données

Mots-clés pour définir les types de données de base

Types entiers : types flottants : char float int double court long double long signé non signé

Une variable de n'importe quel type peut être déclarée non modifiable. Ceci est réalisé en ajoutant le mot-clé const au spécificateur de type. Les objets de type const représentent des données en lecture seule, c'est-à-dire cette variable ne peut pas recevoir de nouvelle valeur. Notez que s'il n'y a pas de spécificateur de type après le mot const, alors le spécificateur de type int est implicite. Si le mot-clé const précède la déclaration des types composites (tableau, structure, mélange, énumération), alors cela conduit au fait que chaque élément doit également être non modifiable, c'est-à-dire une valeur ne peut lui être attribuée qu'une seule fois.

Const double A=2,128E-2 ; const B = 286 ; (const int B=286 est implicite)

Des exemples de déclaration de données composites seront discutés ci-dessous.

1.2.2. Type de données entier

Pour définir des données de type entier, divers mots-clés sont utilisés, qui déterminent la plage de valeurs et la taille de la zone mémoire allouée aux variables (tableau 6).

Tableau 6

Notez que les mots-clés signés et non signés sont facultatifs. Ils indiquent comment le bit zéro de la variable déclarée est interprété, c'est-à-dire que si le mot-clé unsigned est spécifié, alors le bit zéro est interprété comme faisant partie d'un nombre, sinon le bit zéro est interprété comme signé. Si le mot clé non signé est manquant, la variable entière est considérée comme signée. Si le spécificateur de type consiste en un type de clé signé ou non signé suivi d'un identifiant de variable, alors il sera traité comme une variable de type int. Par exemple:

Int non signé n ; non signé int b ; int c; (signé int c est implicite); non signé d; (implique un int d non signé); signé f; (signé int f est implicite).

Notez que le modificateur de type char est utilisé pour représenter un caractère (à partir d'une représentation matricielle de caractères) ou pour déclarer des chaînes littérales. La valeur d'un objet char est le code sur 1 octet correspondant au caractère qu'il représente. Pour représenter les caractères de l'alphabet russe, le modificateur de type d'identifiant de données est un caractère non signé, puisque les codes des lettres russes dépassent la valeur de 127.

La note suivante doit être faite : le langage SI ne définit pas la représentation en mémoire et la plage de valeurs pour les identifiants avec les modificateurs de type int et unsigned int. La taille de la mémoire d'une variable avec le modificateur de type signé int est déterminée par la longueur du mot machine, qui a une taille différente pour différentes voitures. Ainsi, sur les machines 16 bits, la taille du mot est de 2 octets, sur les machines 32 bits, elle est de 4 octets, c'est-à-dire le type int est équivalent types courts int, ou long int selon l'architecture du PC utilisé. Ainsi, un même programme peut fonctionner correctement sur un ordinateur et mal sur un autre. Pour déterminer la longueur de la mémoire occupée par une variable, vous pouvez utiliser l'opérateur sizeof du langage SI, qui renvoie la longueur du modificateur de type spécifié.

Par exemple:

A = taille de (int); b = taille de (long int); c = sizeof(long non signé); d = taille de (court);

Notez également que les constantes octales et hexadécimales peuvent également avoir le modificateur unsigned. Ceci est réalisé en précisant le préfixe u ou U après la constante ; une constante sans ce préfixe est considérée comme signée.

Par exemple:

0xA8C (int signé) ; 01786l (signé longuement); 0xF7u (int non signé) ;

1.2.3. Données flottantes

Pour les variables représentant un nombre à virgule flottante, les modificateurs de type suivants sont utilisés : float, double, long double (dans certaines implémentations du langage long double, il n'y a pas de SI).

Une valeur avec le modificateur de type float prend 4 octets. Parmi ceux-ci, 1 octet est alloué pour le signe, 8 bits pour l'exposant excédentaire et 23 bits pour la mantisse. Notez que le bit le plus significatif de la mantisse est toujours 1, il n'est donc pas rempli, donc la plage de valeurs pour une variable à virgule flottante est d'environ 3,14E-38 à 3,14E+38.

Une valeur double occupe 8 bits de mémoire. Son format est similaire au format float. Les bits mémoire sont répartis comme suit : 1 bit pour le signe, 11 bits pour l'exposant et 52 bits pour la mantisse. Compte tenu du bit haut omis de la mantisse, la plage de valeurs va de 1,7E-308 à 1,7E+308.

Flotteur f, a, b ; doublex, y ;

1.2.4. Panneaux d'affichage

Un pointeur est l'adresse de la mémoire allouée pour accueillir un identifiant (l'identifiant peut être le nom d'une variable, d'un tableau, d'une structure ou d'une chaîne littérale). Si une variable est déclarée comme pointeur, elle contient alors une adresse mémoire où peut être localisée une valeur scalaire de n'importe quel type. Lors de la déclaration d'une variable de type pointeur, vous devez préciser le type d'objet de données dont la variable contiendra l'adresse, ainsi que le nom du pointeur précédé d'un astérisque (ou d'un groupe d'astérisques). Format de déclaration du pointeur :

spécificateur de type [modificateur] * spécificateur.

Le spécificateur de type spécifie le type de l'objet et peut être n'importe quel type de base, type de structure, mélange (ceci sera discuté ci-dessous). En spécifiant le mot-clé void au lieu du spécificateur de type, vous pouvez différer de manière unique la spécification du type auquel le pointeur fait référence. Une variable déclarée comme pointeur vers le type void peut être utilisée pour faire référence à un objet de n'importe quel type. Cependant, afin de pouvoir effectuer des opérations arithmétiques et logiques sur des pointeurs ou sur les objets vers lesquels ils pointent, il est nécessaire de déterminer explicitement le type d'objets lors de l'exécution de chaque opération. De telles définitions de type peuvent être effectuées à l’aide de l’opération de conversion de type.

Les mots-clés const, close, far, huge peuvent être utilisés comme modificateurs lors de la déclaration d'un pointeur. Le mot clé const indique que le pointeur ne peut pas être modifié dans le programme. La taille d'une variable déclarée comme pointeur dépend de l'architecture de l'ordinateur et du modèle de mémoire utilisé pour lequel le programme sera compilé. Les pointeurs vers différents types de données ne doivent pas nécessairement avoir la même longueur.

Pour modifier la taille du pointeur, vous pouvez utiliser les mots-clés près, loin, énorme.

Int non signé * a ; /* la variable a est un pointeur vers le type unsigned int */ double * x; /* la variable x indique un type de données à virgule flottante double précision */ char * fuffer ; /* déclare un pointeur nommé fuffer qui pointe vers une variable de type char */ double nomer; annuler les *adresses ; adresses = &nomer; (double *)adresses++; /* La variable addres est déclarée comme un pointeur vers un objet de n'importe quel type. Par conséquent, l'adresse de n'importe quel objet peut lui être attribuée (& est l'opération de calcul de l'adresse). Cependant, comme indiqué ci-dessus, aucune opération arithmétique ne peut être effectuée sur un pointeur à moins que le type de données vers lesquelles il pointe soit explicitement déterminé. Cela peut être fait en utilisant une opération de conversion (double *) pour convertir les adresses en un pointeur pour taper double, puis en incrémentant l'adresse. */ const * dr; /* La variable dr est déclarée comme un pointeur vers une expression constante, c'est-à-dire la valeur du pointeur peut changer au cours du processus exécution du programme, mais la valeur indiquée ne l'est pas. */ caractère non signé * const w = &obj. /* La variable w est déclarée comme un pointeur constant vers des données char non signées. Cela signifie que w pointera vers le même emplacement mémoire tout au long du programme. Le contenu de cette zone peut être modifié. */

1.2.5. Variables énumérées

Une variable qui peut prendre une valeur dans une liste de valeurs est appelée variable énumérée ou énumération.

Une déclaration d'énumération commence par le mot-clé enum et a deux formats de présentation.

Format 1. enum [enum-tag-name] (enum-list) descriptor[,descriptor...];

Format 2. enum descripteur de nom de balise enum [, descripteur ..] ;

Une déclaration d'énumération spécifie le type de la variable d'énumération et définit une liste de constantes nommées appelée liste d'énumération. La valeur de chaque nom de liste est un entier.

Une variable de type énumération peut prendre la valeur d'une des constantes nommées de la liste. Les constantes de liste nommée sont de type int. Ainsi, la mémoire correspondant à une variable d'énumération est la mémoire nécessaire pour accueillir une valeur int.

Les variables de type enum peuvent être utilisées dans les expressions d'index et comme opérandes dans les opérations arithmétiques et relationnelles.

Dans le premier format 1, les noms et valeurs d'énumération sont spécifiés dans une liste d'énumération. Le nom de balise d'énumération facultatif est un identifiant qui nomme la balise d'énumération définie par la liste d'énumération. Le descripteur nomme une variable d'énumération. Une annonce peut en avoir plusieurs type de variable transferts.

Une liste d'énumération contient une ou plusieurs constructions de la forme :

identifiant [= expression constante]

Chaque identifiant nomme un élément de l'énumération. Tous les identifiants de la liste d'énumération doivent être uniques. S'il n'y a pas d'expression constante, le premier identifiant correspond à la valeur 0, le suivant à la valeur 1, etc. Le nom d'une constante d'énumération est équivalent à sa valeur.

Un identifiant associé à une expression constante prend la valeur spécifiée par cette expression constante. L'expression constante doit être de type int et peut être positive ou négative. L'identifiant suivant dans la liste se voit attribuer la valeur de l'expression constante plus 1 si cet identifiant n'a pas sa propre expression constante. L'utilisation des éléments d'énumération doit obéir aux règles suivantes :

1. La variable peut contenir des valeurs en double.

2. Les identifiants d'une liste d'énumération doivent être distincts de tous les autres identifiants de la même portée, y compris les noms de variables réguliers et les identifiants d'autres listes d'énumération.

3. Les noms de types d'énumération doivent être distincts des autres noms de types d'énumération, de structures et de mélanges dans la même portée.

4. La valeur peut suivre le dernier élément de la liste d'énumération.

Enum semaine ( SUB = 0, /* 0 */ VOS = 0, /* 0 */ POND, /* 1 */ VTOR, /* 2 */ SRED, /* 3 */ HETV, /* 4 */ PJAT /* 5 */ ) rab_ned ;

DANS dans cet exemple une balise énumérable week est déclarée, avec un ensemble de valeurs correspondant, et une variable rab_ned de type week est déclarée.

Le deuxième format utilise le nom de la balise enum pour faire référence à un type d'énumération défini ailleurs. Le nom de la balise d'énumération doit faire référence à une balise d'énumération déjà définie dans la portée actuelle. Étant donné que la balise d'énumération est déclarée ailleurs, la liste d'énumération n'est pas représentée dans la déclaration.

En déclarant un pointeur vers un type de données d’énumération et en déclarant des typedefs pour les types d’énumération, vous pouvez utiliser le nom d’une balise d’énumération avant que cette balise d’énumération ne soit définie. Cependant, la définition enum doit précéder toute utilisation du pointeur de la déclaration typedef vers le type. Une déclaration sans liste ultérieure de descripteurs décrit une balise ou, pour ainsi dire, un modèle d'énumération.

1.2.6. Tableaux

Les tableaux sont un groupe d'éléments du même type (double, float, int, etc.). A partir de la déclaration du tableau, le compilateur doit obtenir des informations sur le type des éléments du tableau et leur nombre. Une déclaration de tableau a deux formats :

descripteur de spécificateur de type [const - expression] ;

descripteur de spécificateur de type ;

Le descripteur est l'identifiant du tableau.

Le spécificateur de type spécifie le type des éléments du tableau déclaré. Les éléments du tableau ne peuvent pas être des fonctions ou des éléments vides.

L'expression constante entre crochets spécifie le nombre d'éléments dans le tableau. Lors de la déclaration d'un tableau, une expression constante peut être omise dans les cas suivants :

Une fois déclaré, le tableau est initialisé,

Le tableau est déclaré comme paramètre formel de la fonction,

SI définit uniquement des tableaux unidimensionnels, mais comme un élément d'un tableau peut être un tableau, des tableaux multidimensionnels peuvent également être définis. Ils sont formalisés par une liste d'expressions constantes suivant l'identifiant du tableau, chaque expression constante étant entourée de ses propres crochets.

Chaque expression constante entre crochets spécifie le nombre d'éléments le long de cette dimension du tableau, de sorte qu'une déclaration de tableau à deux dimensions contient deux expressions constantes, un tableau à trois dimensions en contient trois, et ainsi de suite. Notez qu'en SI, le premier élément d'un tableau a un indice de 0.

Int un; /* représenté sous forme de matrice a a a a a a */ double b; /* vecteur de 10 éléments de type double */ int w = ( ( 2, 3, 4 ), ( 3, 4, 8 ), ( 1, 0, 9 ) );

Dans le dernier exemple, le tableau w est déclaré. Les listes entourées d'accolades correspondent à des chaînes de tableau ; s'il n'y a pas d'accolades, l'initialisation ne sera pas effectuée correctement.

En SI, vous pouvez utiliser des tranches de tableau, comme dans d'autres langages haut niveau(PL1, etc.), cependant, un certain nombre de restrictions sont imposées à l'utilisation des sections. Les sections sont formées en omettant une ou plusieurs paires de crochets. Les paires de crochets ne peuvent être supprimées que de droite à gauche et strictement séquentiellement. Des sections de tableaux sont utilisées pour organiser le processus de calcul en fonctions SI développées par l'utilisateur.

Si vous écrivez s lors de l'appel d'une fonction, alors la chaîne zéro du tableau s sera transmise.

Lorsque vous accédez à un tableau b, vous pouvez écrire, par exemple, b et un vecteur de quatre éléments sera transféré, et accéder à b donnera un tableau bidimensionnel de taille 3 par 4. Vous ne pouvez pas écrire b, ce qui implique qu'un vecteur sera être transféré, car cela ne respecte pas la restriction imposée sur l'utilisation des sections du tableau.

Un exemple de déclaration de tableau de caractères.

char str = "déclaration de tableau de caractères";

Notez qu'il y a un élément supplémentaire dans un caractère littéral, puisque le dernier élément est la séquence d'échappement "\0".

1.2.7. Structures

Les structures sont un objet composite qui comprend des éléments de tout type, à l'exception des fonctions. Contrairement à un tableau qui est un objet homogène, une structure peut être hétérogène. Le type de structure est déterminé par une entrée de la forme :

struct (liste de définitions)

Au moins un composant doit être spécifié dans la structure. La définition des structures est la suivante :

descripteur de type de données ;

où type de données spécifie le type de structure des objets définis dans les descripteurs. Dans leur forme la plus simple, les handles sont des identifiants ou des tableaux.

Struct (double x,y; ) s1, s2, sm; struct (int année ; char moth, jour ; ) date1, date2 ;

Les variables s1, s2 sont définies comme des structures dont chacune est constituée de deux composants x et y. La variable sm est définie comme un tableau de neuf structures. Chacune des deux variables date1, date2 se compose de trois composantes année, papillon et jour. >p>Il existe une autre façon d'associer un nom à un type de structure, elle repose sur l'utilisation d'une balise de structure. Une balise de structure est similaire à une balise de type enum. La balise structure est définie comme suit :

struct tag(liste des descriptions; );

où tag est un identifiant.

L'exemple ci-dessous décrit l'identifiant de l'étudiant sous forme de balise de structure :

Struct student ( nom du personnage ; identifiant int, âge ; char prp ; );

La balise structure permet de déclarer ultérieurement des structures de ce type sous la forme :

balise struct id-list ;

struct étudiant st1,st2 ;

L'utilisation de balises de structure est nécessaire pour décrire les structures récursives. Ce qui suit traite de l'utilisation de balises de structure récursives.

Noeud Struct ( données int; noeud struct * next; ) st1_node;

Le nœud de balise de structure est en effet récursif puisqu'il est utilisé dans sa propre description, c'est-à-dire dans la formalisation du pointeur suivant. Les structures ne peuvent pas être directement récursives, c'est-à-dire une structure de nœuds ne peut pas contenir un composant qui est une structure de nœuds, mais toute structure peut avoir un composant qui est un pointeur vers son type, comme c'est le cas dans l'exemple ci-dessus.

Les composants de la structure sont accessibles en spécifiant le nom de la structure et, séparés par un point, le nom du composant sélectionné, par exemple :

St1.name="Ivanov"; st2.id=st1.id; st1_node.data=st1.age;

1.2.8. Combinaisons (mélanges)

Une union est similaire à une structure, mais un seul des éléments de l’union peut être utilisé (ou en d’autres termes répondu) à tout moment. Le type de jointure peut être spécifié comme suit :

Union ( description de l'élément 1; ... description de l'élément n; );

La principale caractéristique d'une union est que la même zone mémoire est allouée à chacun des éléments déclarés, c'est-à-dire ils se chevauchent. Bien que cette région mémoire soit accessible à l'aide de n'importe lequel des éléments, l'élément prévu à cet effet doit être sélectionné de manière à ce que le résultat obtenu ne soit pas dénué de sens.

Les membres d'un syndicat sont accessibles de la même manière que les structures. La balise union peut être formalisée exactement de la même manière que la balise structure.

L'association est utilisée aux fins suivantes :

Initialiser un objet mémoire en cours d'utilisation si, à un moment donné, un seul objet parmi de nombreux objets est actif ;

Interprétez la représentation sous-jacente d’un objet d’un type comme si cet objet se voyait attribuer un type différent.

La mémoire qui correspond à une variable de type union est déterminée par la quantité nécessaire pour accueillir l'élément le plus long de l'union. Lorsqu'un élément plus court est utilisé, la variable de type union peut contenir de la mémoire inutilisée. Tous les éléments d'une union sont stockés dans la même zone mémoire, en commençant à la même adresse.

Union (char fio; adresses char; int vozrast; int telefon; ) informer; union (int hache; char al; ) ua;

Lorsque vous utilisez un objet infor de type union, vous ne pouvez traiter que l'élément qui a reçu la valeur, c'est-à-dire Après avoir attribué une valeur à l'élément inform.fio, cela ne sert à rien d'accéder à d'autres éléments. La concaténation ua permet un accès séparé aux octets ua.al bas et ua.al haut du nombre à deux octets ua.ax .

1.2.9. Champs de bits

Un élément de la structure peut être un champ de bits qui donne accès à des bits individuels de mémoire. Les champs de bits ne peuvent pas être déclarés en dehors des structures. Vous ne pouvez pas non plus organiser des tableaux de champs de bits et vous ne pouvez pas appliquer l'opération de détermination d'adresse aux champs. En général, le type de structure avec un champ de bits est spécifié comme suit :

Struct ( identifiant non signé 1 : longueur de champ 1 ; identifiant non signé 2 : longueur de champ 2 ; )

longueur - les champs sont spécifiés par une expression entière ou une constante. Cette constante précise le nombre de bits alloués au champ correspondant. Un champ de longueur nulle indique l'alignement sur la limite du mot suivant.

Struct ( non signé a1 : 1 ; non signé a2 : 2 non signé a3 : 5 non signé a4 : 2 ; ) prim;

Les structures de champs de bits peuvent également contenir des composants signés. Ces composants sont automatiquement placés sur les limites de mots appropriées et certains bits de mots peuvent rester inutilisés.

1.2.10. Variables à structure mutable

Très souvent, certains objets programme appartiennent à la même classe et ne diffèrent que par certains détails. Prenons par exemple la représentation de formes géométriques. Les informations générales sur les formes peuvent inclure des éléments tels que la surface et le périmètre. Toutefois, les informations de dimensions géométriques correspondantes peuvent différer en fonction de leur forme.

Prenons un exemple dans lequel des informations sur des formes géométriques sont représentées sur la base de l'utilisation combinée de la structure et de l'union.

Figure de structure ( double surface, périmètre; /* composants communs */ type int; /* attribut de composant */ union /* énumération des composants */ ( double rayon; /* cercle */ double a; /* rectangle */ double b ; /* triangle */ ) geom_fig; ) fig1, fig2 ;

En général, chaque objet figure sera composé de trois éléments : surface, périmètre, type. Le composant de type est appelé étiquette de composant actif car il est utilisé pour indiquer quel composant de l'union geom_fig est actif dans ce moment. Cette structure est appelée structure variable car ses composants changent en fonction de la valeur du label du composant actif (la valeur de type).

Notez qu'au lieu d'un composant de type int, il serait conseillé d'utiliser un type énuméré. Par exemple, comme ça

Enum figure_chess ( CERCLE, BOITE, TRIANGLE ) ;

Les constantes CIRCLE, BOX, TRIANGLE recevront respectivement des valeurs égales à 0, 1, 2. La variable de type peut être déclarée comme ayant un type énuméré :

enum type figure_chess ;

Dans ce cas, le compilateur SI avertira le programmeur des affectations potentiellement erronées, telles que

figure.type = 40 ;

En général, une variable de structure sera composée de trois parties : un ensemble de composants communs, une étiquette pour le composant actif et une partie avec des composants changeants. La forme générale d'une structure variable est la suivante :

Struct (composants communs ; étiquette du composant actif ; union (description du composant 1 ; description du composant 2 ; :: description du composant n ; ) identifiant-union ; ) identifiant-structure ;

Exemple de définition d'une variable de structure nommée helth_record

Structure ( /* informations générales*/ nom du personnage ; /* nom */ int âge ; /* âge */ char sexe; /* sexe */ /* étiquette du composant actif */ /* ( Situation familiale) */ enum merital_status ins; /* partie variable */ union ( /* célibataire */ /* aucun composant */ struct ( /* marié */ char marripge_date; char conjoint_nom; int no_children; ) mariage_info; /* divorcé */ char date_divorced; ) marital_info ; ) dossier_santé ; enum marital_status ( CÉLIBATAIRE, /* célibataire */ MARIAGE, /* marié */ DIVOURÉ /* divorcé */ ) ;

Vous pouvez accéder aux composants de la structure à l'aide de liens :

Helth_record.neme, helth_record.ins, helth_record.marriage_info.marriage_date .

1.2.11. Définir des objets et des types

Comme mentionné ci-dessus, toutes les variables utilisées dans les programmes SI doivent être déclarées. Le type de variable déclaré dépend du mot-clé utilisé comme spécificateur de type et du fait que le spécificateur soit un simple identifiant ou une combinaison d'un identifiant avec un pointeur (astérisque), un tableau (crochets) ou un modificateur de fonction (parenthèses).

Lors de la déclaration d'une variable simple, d'une structure, d'un mélange ou d'une union, ou d'une énumération, le descripteur est un simple identifiant. Pour déclarer un pointeur, un tableau ou une fonction, l'identifiant est modifié en conséquence : un astérisque à gauche, un carré ou des parenthèses à droite.

Notons une caractéristique importante du langage SI : lors de la déclaration, plusieurs modificateurs peuvent être utilisés simultanément, ce qui permet de créer de nombreux descripteurs de types complexes différents.

Cependant, il faut rappeler que certaines combinaisons de modificateurs sont inacceptables :

Les éléments du tableau ne peuvent pas être des fonctions.

Les fonctions ne peuvent pas renvoyer de tableaux ou de fonctions.

Lors de l'initialisation de descripteurs complexes, les crochets et les parenthèses (à droite de l'identifiant) ont priorité sur l'astérisque (à gauche de l'identifiant). Les carrés ou les parenthèses ont la même priorité et sont développés de gauche à droite. Le spécificateur de type est considéré à la dernière étape, lorsque le descripteur a déjà été entièrement interprété. Vous pouvez utiliser des parenthèses pour modifier l'ordre d'interprétation selon vos besoins.

Pour interpréter des descriptions complexes, une règle simple est proposée, qui ressemble à « de l'intérieur vers l'extérieur » et comprend quatre étapes.

1. Commencez par l'identifiant et regardez à droite pour voir s'il y a des carrés ou des parenthèses.

2. Si c’est le cas, interprétez cette partie du descripteur puis regardez vers la gauche à la recherche d’un astérisque.

3. Si à un moment donné une parenthèse fermante est rencontrée à droite, alors toutes ces règles doivent d'abord être appliquées à l'intérieur des parenthèses, puis l'interprétation doit continuer.

4. Interprétez le spécificateur de type.

Int * (* comp ) (); 6 5 3 1 2 4

Cet exemple déclare la variable comp (1) comme un tableau de dix (2) pointeurs (3) vers des fonctions (4) renvoyant des pointeurs (5) vers des valeurs entières (6).

Char * (* (*var) ()) ; 7 6 4 2 1 3 5

La variable var (1) est déclarée comme un pointeur (2) vers une fonction (3) qui renvoie un pointeur (4) vers un tableau (5) de 10 éléments, qui sont des pointeurs (6) vers des valeurs de caractères.

En plus de déclarer des variables de différents types, il est possible de déclarer des types. Ceci peut être fait de deux façons. La première consiste à spécifier un nom de balise lors de la déclaration d'une structure, d'une union ou d'une énumération, puis à utiliser ce nom dans les déclarations de variables et de fonctions comme référence à cette balise. La seconde consiste à utiliser le mot-clé typedef pour déclarer un type.

Lorsqu'il a été annoncé à partir de mot-clé typedef, un identifiant à la place de l'objet décrit, est le nom du type de données introduit en considération, et ce type peut ensuite être utilisé pour déclarer des variables.

Notez que n'importe quel type peut être déclaré à l'aide du mot-clé typedef, y compris les types pointeur, fonction ou tableau. Un nom avec le mot-clé typedef pour les types pointeur, structure et union peut être déclaré avant que ces types ne soient définis, mais dans la portée du déclarant.

Typedef double(*MATH)(); /* MATH - nouveau nom de type représentant un pointeur vers une fonction qui renvoie des valeurs doubles */ MATH cos; /* cos pointeur vers une fonction renvoyant des valeurs de type double */ /* Une déclaration équivalente peut être faite */ double (* cos)(); typedef char FIO /* FIO - tableau de quarante caractères */ FIO person; /* La variable person est un tableau de quarante caractères */ /* Ceci équivaut à une déclaration */ char person;

Lors de la déclaration des variables et des types, les noms de types (MATH FIO) ont été utilisés ici. De plus, les noms de types peuvent être utilisés dans trois autres cas : dans la liste des paramètres formels, dans les déclarations de fonctions, dans les opérations de transtypage de type et dans l'opération sizeof (opération de transtypage de type).

Les noms de type pour les types de base, d’énumération, de structure et de mélange sont les spécificateurs de type pour ces types. Les noms de types pour les types de pointeurs de tableau et de fonctions sont spécifiés à l'aide de descripteurs abstraits comme suit :

spécificateur de type de descripteur abstrait ;

Un gestionnaire abstrait est un handle non-identifiant composé d'un ou plusieurs modificateurs de pointeur, de tableau ou de fonction. Le modificateur de pointeur (*) est toujours donné avant l'identifiant dans le descripteur, et les modificateurs de tableau et de fonction () sont donnés après. Ainsi, pour interpréter correctement un descripteur abstrait, il faut commencer l'interprétation par l'identifiant implicite.

Les descripteurs abstraits peuvent être complexes. Les parenthèses dans les descripteurs abstraits complexes précisent l'ordre d'interprétation de la même manière que l'interprétation des descripteurs complexes dans les déclarations.

1.2.12. Initialisation des données

Lorsqu'une variable est déclarée, une valeur initiale peut lui être attribuée en ajoutant un initiateur à un déclarateur. L'initiateur commence par le signe "=" et a les formes suivantes.

Format 1 : = initiateur ;

Format 2 : = (liste - initiateurs) ;

Le format 1 est utilisé lors de l'initialisation de variables de types de base et de pointeurs, et le format 2 est utilisé lors de l'initialisation d'objets composites.

La variable tol est initialisée avec le caractère "N".

const long mégabute = (1024 * 1024) ;

La variable megabute non modifiable est initialisée avec une expression constante après quoi elle ne peut plus être modifiée.

int statique b = (1,2,3,4);

Un tableau bidimensionnel de b valeurs entières est initialisé ; les éléments du tableau se voient attribuer des valeurs de la liste. La même initialisation peut être effectuée comme ceci :

int statique b = ( ( 1,2 ), ( 3,4 ) );

Lors de l'initialisation d'un tableau, vous pouvez omettre une ou plusieurs dimensions

entier statique b)