variable longue. Types de données en C

En plus de diviser les données en variables et constantes, il existe une classification des données par type. La description des variables consiste principalement à déclarer leur type. Le type de données caractérise la plage de ses valeurs et la forme de représentation dans la mémoire de l'ordinateur. Chaque type est caractérisé par un ensemble d'opérations effectuées sur les données. Traditionnellement, dans les langages de programmation universels, il existe de tels types standards, comme entier, réel, symbolique et logique 3. Notons tout de suite qu'il n'existe pas de type logique en C. Une expression (dans un cas particulier, une variable) est considérée comme vraie si elle est non nulle, en sinon c'est considéré comme faux.

L'existence de deux types numériques (entier et réel) est associée à deux formes possibles de représentation des nombres dans la mémoire de l'ordinateur.

Données type entier stocké sous forme de présentation un point fixe. Il se caractérise par une précision absolue dans la représentation des nombres et l'exécution d'opérations sur ceux-ci, ainsi que par une plage limitée de valeurs numériques. Le type entier est utilisé pour les données qui, en principe, ne peuvent pas avoir de partie fractionnaire (nombre de personnes, de voitures, etc., chiffres et compteurs).

Tapez réel correspond à la forme de représentation numérique point flottant, qui se caractérise par une représentation approximative d'un nombre avec un nombre donné de chiffres significatifs (signes de mantisse) et une large plage de l'ordre du nombre, ce qui permet de représenter aussi bien de très grands que de très petits nombres en valeur absolue. En raison de la représentation approximative des données de type réel, leur il est incorrect de comparer pour l'égalité.

Dans les implémentations modernes des langages de programmation universels, il existe généralement plusieurs types entiers et plusieurs types réels, chacun étant caractérisé par sa taille de mémoire allouée pour une valeur et, par conséquent, sa plage de valeurs numériques et pour les types réels - et sa précision. (le nombre de chiffres de la mantisse).

Données type de caractère prendre des valeurs sur l'ensemble des valeurs acceptables de cet ordinateur personnages. Un octet est alloué pour stocker une valeur de caractère ; les caractères sont codés conformément à une table de codage standard (généralement ASCII).

Il existe 4 types de base en C :

carboniser- le type de caractère ;

int- tout un type,

flotter- type réel simple précision,

double- type réel double précision.

Pour définir des types dérivés, utilisez qualificatifs:court(court) - utilisé avec le type int,long(long) - utilisé avec les types int Et double;signé(avec un signe), non signé(non signé) - s'applique à tout type entier. En l'absence du mot non signé, la valeur est considérée comme signée, c'est-à-dire c'est-à-dire que la valeur par défaut est signée. En raison de l'admissibilité d'une combinaison arbitraire de qualificatifs et de noms de types de base, un type peut avoir plusieurs désignations. Les informations sur les types C standard sont présentées dans les tableaux 1 et 2. Les descripteurs de synonymes sont répertoriés dans les cellules de la première colonne, séparés par des virgules.

Tableau 1. Types de données entiers C standard

Type de données

Plage de valeurs

char, char signé

non signé int, non signé

int, signé int, court int, court

2147483648...2147483647

Fait intéressant, en C, le type char peut être utilisé comme caractère ou comme type entier, selon le contexte.

Tableau 2. Types de données réelles standard C

Commentaire. Pour écrire les programmes de la première partie du manuel, nous aurons principalement besoin deux types:flotterEtint.

Les variables sont utilisées pour stocker diverses données dans les langages de programmation. Une variable est une zone de mémoire qui porte un nom, autrement appelé identifiant.

Donnant Nom de variable, le programmeur nomme en même temps la zone mémoire où les valeurs de la variable à stocker seront écrites avec le même nom.

C'est un bon style de nommer les variables de manière significative. Il est permis d'utiliser des minuscules et lettres majuscules, des chiffres et un trait de soulignement, qui est considéré comme une lettre en C. Le premier caractère doit être une lettre et le nom de la variable ne doit contenir aucun espace. DANS versions modernes les compilateurs n'ont pratiquement aucune limite sur la longueur du nom. Le nom de la variable ne peut pas correspondre aux mots-clés réservés. Les lettres majuscules et minuscules dans les noms de variables sont différentes, les variables un Et UN- différentes variables.

Mots-clés réservés auto double int struct break else long switch register tupedef char extern return void case float non signé par défaut pour l'union signée faire si sizeof volatile continuer enum short while
En C, toutes les variables doivent être déclarées. Cela signifie que, d'une part, au début de chaque programme ou fonction, vous devez fournir une liste de toutes les variables utilisées, et d'autre part, indiquer le type de chacune d'elles.

Lorsqu'une variable est déclarée, le compilateur lui alloue de l'espace mémoire en fonction de son type. Par des moyens standards AVR GCC fonctionne avec les types de données carboniser(type de caractère) et int(type entier).

Types de variables

Tapez char

carboniser- est le type le plus économique. Le type char peut être signé ou non signé. Noté en conséquence comme " caractère signé" (type signé) et " caractère non signé" (type non signé). Le type signé peut stocker des valeurs comprises entre -128 et +127. Non signé - de 0 à 255. Une variable char a 1 octet de mémoire (8 bits).

Mots-clés (modificateurs) signé Et non signé indique comment le bit zéro de la variable déclarée est interprété, c'est-à-dire que si le mot-clé non signé 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é.

Tapez int

Valeur entière int Peut être court(court) ou long(long).

Mot-clé (modificateur) court placé après les mots-clés signé ou non signé. Ainsi, on distingue les types suivants : entier court signé, entier court non signé, entier long signé, entier long non signé.

Type de variable signé court int(entier court signé) peut prendre des valeurs de -32768 à +32767, entier court non signé(entier court non signé) - de 0 à 65535. Exactement deux octets de mémoire (16 bits) sont alloués pour chacun d'eux.

Lorsqu'il est annoncé type de variable signé court int mots clés signé Et court peut être omis, et un tel type de variable peut être déclaré simplement int. Il est également possible de déclarer ce type comme un mot-clé court.

Variable entier court non signé peut être déclaré comme entier non signé ou court métrage non signé.

Pour chaque taille signé long int ou entier long non signé 4 octets de mémoire sont alloués (32 bits). Les valeurs des variables de ce type peuvent être comprises respectivement entre -2147483648 et 2147483647 et entre 0 et 4294967295.

Il existe également des variables comme long long int, pour lequel 8 octets de mémoire sont alloués (64 bits). Ils peuvent également être signés ou non. Pour un type signé, la plage de valeurs va de -9223372036854775808 à 9223372036854775807, pour un type non signé - de 0 à 18446744073709551615. Un type signé peut être déclaré simplement par deux mots-clés très longtemps.

Taper Gamme Portée hexadécimale Taille
caractère non signé 0 ... 255 0x00...0xFF 8 bits
caractère signé
ou simplement
carboniser
-128 ... 127 -0x80...0x7F 8 bits
entier court non signé
ou simplement
entier non signé ou court métrage non signé
0 ... 65535 0x0000 ... 0xFFFF 16 bits
signé court int ou signé en entier
ou simplement
court ou int
-32768 ... 32767 0x8000...0x7FFF 16 bits
entier long non signé
ou simplement
non signé depuis longtemps
0 ... 4294967295 0x00000000 ... 0xFFFFFFFF 32 bits
signé longtemps
ou simplement
long
-2147483648 ... 2147483647 0x80000000 ... 0x7FFFFFFF 32 bits
non signé depuis longtemps 0 ... 18446744073709551615 0x0000000000000000 ... 0xFFFFFFFFFFFFFFFF 64 bits
signé depuis longtemps
ou simplement
très longtemps
-9223372036854775808 ... 9223372036854775807 0x8000000000000000 ... 0x7FFFFFFFFFFFFFFFF 64 bits

Les variables sont déclarées dans une instruction de déclaration. Une instruction de déclaration consiste en une spécification de type et une liste de noms de variables séparés par des virgules. Il doit y avoir un point-virgule à la fin.

Une déclaration de variable a format suivant:

[modificateurs] type_specifier identifiant [, identifiant] ...

Modificateurs- mots clés signé, non signé, court, long.
Spécificateur de type- mot-clé carboniser ou int, qui détermine le type de la variable déclarée.
Identifiant- Nom de variable.

Exemple : char x ; int a, b, c; non signé long long y;
De cette façon, les variables seront déclarées X, un, b, c, oui. Vers une variable X il sera possible d'écrire des valeurs de -128 à 127. Dans les variables un, b, c- de -32768 à +32767. Vers une variable oui- de 0 à 18446744073709551615.

Initialiser la valeur d'une variable lors de la déclaration

Lorsqu'elle est déclarée, une variable peut être initialisée, c'est-à-dire se voir attribuer une valeur initiale. Vous pouvez procéder comme suit. entier x = 100 ; Ainsi, dans la variable X Une fois annoncé, le nombre 100 sera immédiatement inscrit.

Il est préférable d'éviter de mélanger les variables initialisées dans une seule instruction de déclaration, c'est-à-dire qu'il est préférable de déclarer les variables initialisées sur des lignes distinctes.

Constantes

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. Variables avec type const est une donnée en lecture seule, ce qui signifie que la variable ne peut pas se voir attribuer une nouvelle valeur. Si après le mot const S'il n'y a pas de spécificateur de type, alors les constantes sont traitées comme des valeurs signées et se voient attribuer un type int ou long int selon la valeur de la constante : si la constante est inférieure à 32768, alors on lui attribue le type int, sinon long int.

Exemple : const long int k = 25 ; const m = -50 ; // implicite const int m=-50 const n = 100 000 ; // implicite const long int n=100000

Affectation

Le signe "=" est utilisé pour l'affectation en C. L'expression à droite du signe d'affectation est évaluée et la valeur résultante est affectée à la variable à gauche du signe d'affectation. Dans ce cas, la valeur précédente stockée dans la variable est effacée et remplacée par une nouvelle.

L'opérateur "=" ne doit pas être compris comme une égalité.
Par exemple, l'expression a = 5 ; doit être lu comme "attribuer la variable a à 5".

Exemples : x = 5 + 3 ; // additionne les valeurs 5 et 3, // assigne le résultat à la variable x (écrit dans la variable x) b = une + 4 ; // ajoute 4 à la valeur stockée dans la variable a, // assigne le résultat résultant à la variable b (écrit dans la variable b) b = b + 2 ; // ajoute 2 à la valeur stockée dans la variable b, // assigne le résultat résultant à la variable b (écrit dans la variable b)
Sur le côté droit, la valeur de la variable peut être utilisée plusieurs fois : c = b * b + 3 * b ;

Exemple : x = 3 ; // la variable x recevra la valeur 3 y = x + 5 ; // le nombre 5 sera ajouté à la valeur stockée dans la variable x, // le résultat résultant sera écrit dans la variable y z = x * y ; // les valeurs des variables x et y seront multipliées, // le résultat sera écrit dans la variable z z = z-1 ; // 1 sera soustrait de la valeur stockée dans la variable z // le résultat sera écrit dans la variable z
Ainsi, dans la variable z le numéro 23 sera stocké

Sauf opérateur simple affectations "=", en C il existe plusieurs autres opérateurs d'affectation combinés : "+=", "-=", "*=
Exemples : x += y ; // identique à x = x + y ; - ajoutez x et y // et écrivez le résultat dans la variable x x -= oui ; // identique à x = x - y ; - soustraire la valeur y de x // et écrire le résultat dans la variable x x *= oui ; // identique à x = x * y ; - multipliez x par y // et écrivez le résultat dans la variable x x /= oui ; // identique à x = x / y ; - diviser x par y // et écrire le résultat dans la variable x x %= oui ; // identique à x = x % y ; // calcule le reste entier en divisant x par y // et écrit le résultat dans la variable x

Incrémenter et décrémenter

Si vous devez changer la valeur d'une variable en 1, utilisez incrément ou décrémenter.

Incrément- l'opération consistant à augmenter de 1 la valeur stockée dans une variable.

Exemple : x++ ; // la valeur de la variable x sera augmentée de 1$WinAVR = ($_GET["avr"]); si($WinAVR) include($WinAVR);?>
Décrémenter- l'opération consistant à diminuer de 1 la valeur stockée dans une variable.

Exemple : x-- ; // la valeur de la variable x sera diminuée de 1
L'incrément et le décrément sont des opérateurs d'affectation. Lorsque vous utilisez la décrémentation et l'incrémentation avec l'opérateur d'affectation "=", utilisez la notation postfixe (x++) ou préfixe (++x). L'entrée du préfixe est exécutée en premier.

Exemples : y = x++ ;
Supposons que dans la variable X la valeur 5 a été stockée. Puis dans oui la valeur 5 sera écrite, après quoi la valeur de la variable X sera augmenté de 1. Ainsi, dans oui sera 5, et dans X- 6. y = --x;
Si dans X Si la valeur 5 a été stockée, alors la décrémentation sera effectuée en premier Xà 4 et ensuite cette valeur sera affectée à la variable oui. Ainsi, X Et oui se verra attribuer la valeur 4.

Le programmeur dit :

Bonjour! J'ai lu votre article. J'étais très triste et drôle à la fois. Cette phrase est particulièrement meurtrière: "Puisqu'une variable de type char est souvent utilisée comme tableau, le nombre de valeurs possibles est déterminé." 😆 😆 😆
Je ne me moque pas de toi. Créer un site internet est vraiment un exploit. Je veux juste vous soutenir avec des conseils et signaler quelques erreurs.

1. La valeur d'une variable de type char est affectée comme suit :

Ici:

Caractère a = *"A" ;

Le pointeur vers le tableau est désadressé et par conséquent la valeur du premier élément du tableau est renvoyée, c'est-à-dire 'UN'

2. La réinitialisation s'effectue comme suit :

Caractère a = NULL ;
char b = ();

//Et voici comment la ligne dans le corps du programme est effacée

"" - ce symbole est appelé terminateur zéro. Il est placé en fin de ligne. Vous-même, sans le savoir, avez rempli le tableau s1 de votre article avec ce symbole. Mais il était possible d'attribuer ce symbole uniquement à l'élément zéro du tableau.

3. N'hésitez pas à utiliser la terminologie.
Le signe = est une opération d’affectation.
Le signe * est une opération de désadressage.
Je veux dire ce fragment de l'article : "Tout s'est avéré si simple, avant le signe = il fallait mettre un signe * et il fallait déclarer le numéro de l'élément (zéro correspond au premier)"

Ne vous méprenez pas, l'article ne peut pas exister sous sa forme actuelle. Ne soyez pas paresseux, réécrivez-le.
Vous avez une grande responsabilité ! Je suis sérieux. Les pages de votre site sont incluses dans la première page des résultats Yandex. Beaucoup de gens ont déjà commencé à répéter vos erreurs.

Bonne chance! Tu peux le faire!

:
Je le sais depuis longtemps, c’est juste difficile de relire constamment 200 articles pour corriger quelque chose. Et certains types impolis écrivent de telle manière que même sachant ce qu’il est préférable de corriger, ils ne sont pas du tout disposés à le corriger.

Je me ferai un plaisir de corriger d'autres erreurs. corriger les inexactitudes si elles apparaissent. J'apprécie ton aide. merci, je le sais depuis longtemps, c'est juste difficile de relire constamment 200 articles pour corriger quelque chose. Et certains types impolis écrivent de telle manière que même sachant ce qu’il est préférable de corriger, ils ne sont pas du tout disposés à le corriger.
Avec votre char b = (); Il ne s’agit pas du tout d’une réduction à zéro. Ils devraient au moins vérifier.
si on parle du caractère nul "" ; Je savais bien, lorsque j'en ai rempli la ligne, que le but était de montrer un véritable nettoyage, et non quelque chose de visible à l'œil nu, car la ligne contient des déchets, qui gênent parfois. Vous devriez être plus prudent avec les termes vous-même, "symbole de terminaison nul" ou simplement "symbole nul", pas un terminateur))) Et le symbole de terminaison semble tout simplement cool.

Je moderniserai l’article, mais je ne passerai pas au style de quelqu’un d’autre. Si je pense qu’il est plus facile pour un débutant de le comprendre de cette façon plutôt que de la façon dont il le souhaite, alors je le laisserai ainsi. Ne vous méprenez pas non plus. Le mot « signe » est beaucoup plus facile à comprendre et à retenir pour un débutant faible que la définition et le nom de chaque signe. Il n’y a aucune erreur là-dedans, c’est un signe – un signe. Moins l’accent est mis sur l’un, plus l’accent est mis sur l’autre.

Je me ferai un plaisir de corriger d'autres erreurs. corriger les inexactitudes si elles apparaissent. J'apprécie ton aide. Merci.

Bonjour à nouveau!
Je veux clarifier. Le terme « zéro-terminateur » (terminator de l'anglais limiteur) a été utilisé par mon professeur à l'université. Apparemment, c'est de la vieille école !
Quant à la réinitialisation des lignes.
char b = (); Il s’agit véritablement d’une réinitialisation. Le tableau entier est rempli de zéros. Si vous ne me croyez pas, jetez un œil !
Si l'on considère une ligne dans son sens naturel et quotidien, alors une ligne « vide » sera une ligne dans laquelle il n'y a pas un seul caractère. Ainsi, dans 99,9% des cas, il suffit de mettre un caractère nul au début. En règle générale, une chaîne est traitée jusqu'au premier caractère nul, et les caractères qui suivent n'ont plus d'importance. Je comprends que vous souhaitiez réinitialiser la ligne. Je viens de décider de proposer une option classique qui a fait ses preuves.

:
Lorsque "Habituellement, le traitement des chaînes va jusqu'au premier caractère nul et les caractères qui suivent n'ont plus d'importance" - oui, la chaîne est annulée
Si nous considérons la « véritable remise à zéro de toutes les cellules d'une ligne (dont j'ai parlé) » - non, pas de remise à zéro, et même le premier caractère n'est pas nul. J'ai coché cette option. MinGW(CodeBlock) - le tableau entier donne le caractère "a"
Je ne pense pas que cela soit matière à débat.

En programmation, un type de données est un ensemble de deux ensembles : un ensemble de valeurs et un ensemble d'opérations qui peuvent leur être appliquées. Par exemple, les opérations d'addition (+), de multiplication (*), de division entière (/), de reste (%) et de soustraction (−) peuvent être appliquées à un type de données entier non négatif constitué d'un ensemble fini de nombres naturels.

Un langage de programmation possède généralement un ensemble de types de données primitifs, types fournis par le langage de programmation en tant qu'unité de base intégrée. En C++, le créateur du langage appelle ces types types fondamentaux. Les types fondamentaux en C++ sont :

  • booléen(bool);
  • caractère (par exemple char);
  • int (par exemple int);
  • virgule flottante (par exemple float);
  • énumérations (définies par le programmeur);
  • vide .

En plus de ceux répertoriés, les types suivants sont construits :

  • démonstratif (par exemple int*) ;
  • tableaux (par exemple char);
  • référence (par exemple double&);
  • d'autres structures.

Passons à la notion de littéral (par exemple, 1, 2.4F, 25e-4, « a », etc.) : littéral - enregistrer dans code source programme représentant une valeur fixe. En d’autres termes, un littéral est simplement une représentation d’un objet (valeur) d’un certain type dans le code d’un programme. C++ a la capacité d’écrire des valeurs entières, à virgule flottante, de caractère, booléennes et de chaîne.

Un littéral de type entier peut s’écrire :

  • 10ème système de numérotation. Par exemple, 1205 ;
  • 8ème système numérique au format 0 + chiffre. Par exemple, 0142 ;
  • 16ème système numérique au format 0x + nombre. Par exemple, 0x2F.

24, 030, 0x18 - ce sont toutes des entrées du même numéro dans différents systèmes Compte.
Pour écrire des nombres à virgule flottante, utilisez la notation par points : 0,1, .5, 4. - soit en
notation exponentielle - 25e-100. Il ne devrait y avoir aucun espace dans un tel enregistrement.

Le nom auquel on peut associer des valeurs écrites en littéraux s'appelle une variable. Une variable est une zone de mémoire nommée ou autrement adressable dont l'adresse peut être utilisée pour accéder aux données. Ces données sont écrites, réécrites et effacées en mémoire d'une certaine manière lors de l'exécution du programme. Une variable permet d'accéder à tout moment aux données et, si nécessaire, de les modifier. Les données pouvant être récupérées à partir d'un nom de variable sont appelées la valeur de la variable.
Pour utiliser une variable dans un programme, elle doit être déclarée, et si nécessaire, elle peut être définie (= initialisée). La déclaration d'une variable dans le texte du programme contient nécessairement 2 parties : le type de base et le déclarateur. Le spécificateur et l'initialiseur sont des parties facultatives :

Exemple Const int = 3 ; // ici const est un spécificateur // int est le type de base // exemple est le nom de la variable // = 3 - initialiseur.

Le nom de la variable est une séquence de caractères composée de lettres de l'alphabet latin (minuscules et majuscules), de chiffres et/ou d'un trait de soulignement, mais le premier caractère ne peut pas être un chiffre. Le nom de la variable doit être choisi de manière à ce qu'il soit toujours facile de deviner ce qu'elle stocke, par exemple « monthPayment ». Dans les notes et dans la pratique, nous utiliserons la notation CamelCase pour les règles d'enregistrement des variables. Le nom de la variable ne peut pas coïncider avec des mots réservés dans le langage ; des exemples de tels mots sont : if, while, function, goto, switch, etc.

En plus du nom de la variable, le déclarateur peut contenir caractères supplémentaires:

  • * - pointeur ; avant le nom ;
  • *const - pointeur constant ; avant le nom ;
  • & - lien; avant le nom ;
  • - tableau; après le nom ;
  • () - fonction; après le nom.

Un initialiseur vous permet de définir une valeur pour une variable immédiatement après sa déclaration. L'initialiseur commence par un littéral d'égalité (=), puis définit la valeur de la variable. De manière générale, le signe égal en C++ désigne une opération d'affectation ; avec son aide, vous pouvez définir et modifier la valeur d'une variable. Pour différents typesça peut être différent.

Le spécificateur spécifie des attributs supplémentaires autres que le type. Le spécificateur const donné dans l'exemple vous permet d'interdire les modifications ultérieures de la valeur de la variable. Ces variables immuables sont appelées constantes ou constantes.

Déclarer une constante sans initialisation ne fonctionnera pas pour des raisons logiques :

Const int EMPTY_CONST ; // erreur, la variable constante n'est pas initialisée const int EXAMPLE = 2; // constante de valeur 2 EXEMPLE = 3; // erreur, tentative d'attribuer une valeur à une variable constante

Lors de la dénomination des constantes, il est d'usage d'utiliser uniquement des lettres majuscules, en séparant les mots par un trait de soulignement.

Types de données de base en C++

En examinant chaque type, le lecteur ne doit pas oublier la définition du type de données.

1. Type entier (char, court (int), int, long (int), long long)

D'après le nom, il est facile de comprendre que l'ensemble des valeurs est constitué d'entiers. De plus, l'ensemble des valeurs de chacun des types répertoriés peut être signé ou non signé. Le nombre d'éléments contenus dans un ensemble dépend de la taille de la mémoire utilisée pour stocker la valeur de ce type. Par exemple, pour une variable de type char 1 octet de mémoire est alloué, donc le total des éléments sera :

  • 2 8N = 2 8 * 1 = 256, où N est la taille de la mémoire en octets pour stocker la valeur

Dans ce cas, les plages d'entiers disponibles sont les suivantes :

  • - pour les caractères non signés
  • [-128..127] - pour les caractères signés

Par défaut, une variable entière est considérée comme signée. Pour indiquer dans le code qu'une variable doit être non signée, un attribut signé est ajouté au type de base à gauche, c'est-à-dire non signé:

Valeurs longues non signées ; // spécifie un type entier (long) non signé.

Les types répertoriés diffèrent uniquement par la taille de la mémoire requise pour le stockage. Le langage C++ étant assez dépendant de la machine, le standard du langage garantit uniquement la condition suivante :

  • 1 = taille du caractère ≤ taille courte ≤ taille int ≤ taille longue.

Généralement, les tailles des types sont les suivantes : char - 1, short - 2, int - 4, long -8, long long - 8 octets.

Vous pouvez effectuer des opérations arithmétiques avec des valeurs de type entier : +, -, *, /, % ; opérations de comparaison : ==, !=,<=, <, >, >=; opérations sur les bits : &, |, xor,<<, >>.
La plupart des opérations, comme l’addition, la multiplication, la soustraction et la comparaison, sont faciles à comprendre. Parfois, après avoir fait opérations arithmétiques, le résultat peut être en dehors de la plage de valeurs ; dans ce cas, le programme générera une erreur.
La division entière (/) trouve la partie entière d'un entier divisée par un autre. Par exemple:

  • 6 / 4 = 1;
  • 2 / 5 = 0;
  • 8 / 2 = 4.

Le symbole de pourcentage (%) désigne l'opération de détermination du reste de la division de deux entiers :

  • 6 % 4 = 2;
  • 10 % 3 = 1.

Les opérations au niveau du bit sont plus difficiles à comprendre : & (AND), | (OU), xor (OU exclusif),<< (побитовый сдвиг влево), >> (décalage au niveau du bit vers la droite).

Les opérations sur bits AND, OR et XOR appliquent l'opération logique correspondante à chaque bit d'information :

  • 1 10 = 01 2
  • 3 10 = 11 2
  • 1 10 & 3 10 = 01 2 & 11 2 = 01 2
  • 1 10 | 3 10 = 01 2 | 11 2 = 11 2
  • 1 10 xou 3 10 = 01 2 xou 11 2 = 10 2

Dans le traitement d'image, 3 canaux sont utilisés pour la couleur : rouge, bleu et vert - plus la transparence, qui sont stockés dans une variable int, car chaque canal a une plage de valeurs de 0 à 255. Dans le système de nombres hexadécimaux, une certaine valeur s'écrit comme suit : 0x180013FF ; alors la valeur 18 16 correspond au canal rouge, 00 16 - bleu, 13 16 - vert, FF - canal alpha (transparence). Pour sélectionner un canal spécifique parmi un tel nombre entier, ce qu'on appelle le canal est utilisé. masque, où les positions qui nous intéressent sont F 16 ou 1 2. Autrement dit, pour mettre en évidence la valeur du canal bleu, vous devez utiliser un masque, c'est-à-dire au niveau du bit ET :

Int canal_bleu = 0x180013FF & 0x00FF0000 ;

Après quoi la valeur résultante est décalée vers la droite du nombre de bits requis.

Un décalage de bits décale un nombre vers la gauche ou la droite d'autant de chiffres binaires que spécifié sur le côté droit de l'opération. Par exemple, le nombre 39 pour le type char s'écrit en binaire comme suit : 00100111. Ensuite :

Char binaireExemple = 39; // 00100111 char résultat = binaireExemple<< 2; // сдвигаем 2 бита влево, результат: 10011100

Si la variable est de type non signé, alors le résultat sera le nombre 156, pour un type signé il est égal à -100. Notez que pour les types entiers signés, une unité dans le bit le plus significatif de la représentation binaire est un signe que le nombre est négatif. Dans ce cas, une valeur sous forme binaire composée de tous des uns correspond à -1 ; si 1 n'est que dans le chiffre le plus significatif et que les chiffres restants sont des zéros, alors un tel nombre a la valeur minimale pour un type particulier : pour char, il est -128.

2. Type à virgule flottante (float, double (float))

L'ensemble des valeurs à virgule flottante est un sous-ensemble de nombres réels, mais tous les nombres réels ne sont pas représentables en binaire, ce qui conduit parfois à des erreurs stupides :

Valeur flottante = 0,2 ; valeur == 0,2 ; // erreur, la valeur ici ne sera pas égale à 0,2.

Lorsqu'il travaille avec des variables à virgule flottante, le programmeur ne doit pas utiliser de test d'égalité ou d'inégalité ; à la place, un test pour se situer dans un certain intervalle est généralement utilisé :

Valeur - 0,2< 1e-6; // ok, подбирать интервал тоже нужно осторожно

En plus des opérations de comparaison, le type à virgule flottante prend en charge 4 opérations arithmétiques qui correspondent entièrement aux opérations mathématiques avec des nombres réels.

3. Type booléen (logique) (bool)

Se compose de seulement deux valeurs : vrai (vrai) et faux (faux). Pour travailler avec des variables de ce type, des opérations logiques sont utilisées : ! (NON), == (égalité), != (inégalité), && (ET logique), || (OU logique). Le résultat de chaque opération se trouve dans la table de vérité correspondante. Par exemple:

X Y XOR0 0 0 0 1 1 1 0 1 1 1 0

4. Type de caractère (char, wchar_t)

Le type char n'est pas seulement un type entier (généralement ce type est appelé octet), mais également un type de caractère, stockant le numéro de caractère de la table sous forme de caractère ASCII. Par exemple, le code 0x41 correspond au caractère « A » et 0x71 au caractère « t ».

Parfois, il devient nécessaire d'utiliser des caractères qui ne sont pas fixés dans les tables ASCII et nécessitent donc plus d'un octet pour le stockage. Il existe un caractère large pour eux (wchar_t).

5.1. Tableaux

Les tableaux vous permettent de stocker un ensemble séquentiel d'éléments du même type. Un tableau est stocké en mémoire sous forme de bloc contigu, vous ne pouvez donc pas déclarer un tableau sans spécifier sa taille. Pour déclarer un tableau, des crochets () sont écrits après le nom de la variable indiquant sa taille. Par exemple:

Int monArray ; // Tableau de 5 éléments de type entier

Pour initialiser un tableau, les valeurs sont répertoriées dans accolades. Vous ne pouvez initialiser de cette manière qu'au moment de la déclaration de la variable. D'ailleurs, dans ce cas, il n'est pas nécessaire de préciser la taille du tableau :

Cotes Int = (1, 3, 7, 9, 11) ; // Le tableau est initialisé avec 5 valeurs

Pour accéder à une valeur spécifique dans un tableau (élément du tableau), utilisez l'opération d'accès à l'index () indiquant le numéro de l'élément (les nombres commencent à 0). Par exemple:

Chances; // accès au premier élément du tableau. Renvoie la valeur 1 cote ; // accès au troisième élément. Renvoie la valeur 7 cotes = 13 ; // Attribue une nouvelle valeur au 5ème élément du tableau odds ; // erreur d'accès

5.3. Cordes

Pour écrire une chaîne, les programmeurs utilisent l’idée qu’une chaîne est une série séquentielle (tableau) de caractères. Pour identifier la fin d'une ligne, utilisez le caractère spécial de fin de ligne : '\0'. Ces caractères spéciaux, constitués d'une barre oblique inverse et d'un caractère d'identification, sont appelés caractères de contrôle ou d'échappement. Il y a aussi, par exemple, '\n' - le début d'une nouvelle ligne, '\t' - la tabulation. Pour écrire une barre oblique inverse dans une chaîne, l'échappement est utilisé - une autre barre oblique est placée avant le signe lui-même : '\'. L'échappement est également utilisé pour écrire des guillemets.

Créons une variable chaîne :

Char textExample = ('T', 'e', ​​​​'s', 't', '\0'); // la chaîne « Test » est écrite

Il existe une notation simplifiée pour l'initialisation d'une chaîne :

Char textExample = « Test » ; // Le dernier caractère n'est pas écrit, mais la taille est toujours de 5

Sans entrer dans les détails, voici un autre type de données utile : la chaîne. Cordes
Ce type peut par exemple être ajouté :

Chaîne bonjour = "Bonjour" ; nom de chaîne = "Max!"; chaîne bonjour_nom = bonjour + nom ; // Récupère la chaîne "Bonjour, Max !"

6. Lien

Int a = 2 ; // la variable "a" pointe vers la valeur 2 int &b = a; // la variable « b » pointe au même endroit que « a » b = 4 ; // en changeant la valeur de b, le programmeur change la valeur de a. Maintenant a = 4 int &c = 4; // erreur, vous ne pouvez pas faire ça car la référence ne peut pas recevoir de valeur

7. Indice

Pour comprendre ce type de données, vous devez vous rappeler que de nombreuses valeurs de ce type sont les adresses des cellules mémoire où commencent les données. Le pointeur prend également en charge les opérations d'addition (+), de soustraction (-) et de déréférencement (*).

Les adresses 0x0 signifient que le pointeur est vide, c'est-à-dire ne pointe vers aucune donnée. Cette adresse a son propre littéral - NULL :

Int *nullPtr = NULL; // pointeur nul

Ajouter et soustraire une adresse avec un entier ou une autre adresse permet
se déplacer dans la mémoire disponible pour le programme.

L'opération de récupération de données à partir d'une adresse stockée dans un pointeur est appelée déréférencement (*). Le programme lit le nombre requis de cellules mémoire et renvoie la valeur stockée en mémoire.

Int valeurEnMémoire = 2 ; // définit une variable de type entier int *somePtr = // copie l'adresse de la variable, ici & - renvoie l'adresse de la variable somePtr; // adresse de la cellule mémoire, par exemple 0x2F *somePtr; // la valeur est stockée dans 4 cellules : 0x2F, 0x30, 0x31 et 0x32

L'opération d'affectation, qui est syntaxiquement la même que l'opération de copie, n'est pas disponible pour les pointeurs. En d’autres termes, vous pouvez copier l’adresse d’un autre pointeur ou l’adresse d’une variable, mais vous ne pouvez pas déterminer vous-même la valeur de l’adresse.

Le pointeur lui-même est stocké en mémoire, comme les valeurs de variables d'autres types, et occupe 4 octets, vous pouvez donc créer un pointeur vers un pointeur.

8. Transferts

Les énumérations sont le seul type de base défini par le programmeur. En gros, une énumération est un ensemble ordonné de constantes entières nommées, le nom de l'énumération étant le type de base.

Couleur d'énumération (ROUGE, BLEU, VERT);

Par défaut, ROUGE = 0, BLEU = 1, VERT = 2. Par conséquent, les valeurs peuvent être comparées entre elles, c'est-à-dire ROUGE< BLUE < GREEN. Программист при объявлении перечисления может самостоятельно задать значения каждой из констант:

Accès enum (LECTURE = 1, WRITE = 2, EXEC = 4) ;

Il est souvent pratique d'utiliser des énumérations dont les valeurs sont des puissances de deux, car en représentation binaire, un nombre qui est une puissance de 2 sera composé de 1 et de zéros. Par exemple:

8 10 = 00001000 2

Le résultat de l’addition de ces nombres indique toujours clairement quels nombres ont été ajoutés :

37 10 = 00100101 2 = 00000001 2 + 00000100 2 + 00100000 2 = 1 10 + 4 10 + 32 10

Vide

Syntaxiquement, le type void appartient aux types fondamentaux, mais il ne peut être utilisé que dans le cadre de types plus complexes, car Il n'y a aucun objet de type void. Généralement, ce type est utilisé pour indiquer qu'une fonction n'a pas de valeur de retour ou comme type de base d'un pointeur vers des objets de types non définis :

Objet vide ; // erreur, il n'y a aucun objet de type void void // erreur, il n'y a aucune référence à void void *ptr; // ok, stocke un pointeur vers un type inconnu

Souvent, nous utiliserons void spécifiquement pour indiquer qu'une fonction ne renvoie aucune valeur. Un pointeur de type void est utilisé lorsque le programmeur assume l'entière responsabilité de l'intégrité de la mémoire et de la conversion de type correcte.

Casting

Il est souvent nécessaire de convertir la valeur d'une variable d'un type en un autre. Dans le cas où l'ensemble des valeurs du type d'origine est un sous-ensemble d'un type plus grand (par exemple, int est un sous-ensemble de long et long est un double), le compilateur est capable de implicitement ( implicitement) changez le type de valeur.

entier = 2 ; float flottant = entier ; // flottant = 2.0

Une conversion de type inversée sera effectuée avec perte d'informations, donc seule la partie entière du nombre à virgule flottante restera, la partie fractionnaire sera perdue.

Il existe la possibilité d'une conversion de type explicite ; pour cela, à gauche de la variable ou de toute valeur du type d'origine, écrivez entre parenthèses le type vers lequel le transtypage sera effectué :

Valeur int = (int) 2,5 ;

Opérations unaires et binaires

Les opérations que nous avons effectuées précédemment sont appelées binaires : à gauche et à droite du symbole de l'opération se trouvent des valeurs ou des variables, par exemple 2 + 3. En plus des opérations binaires, les langages de programmation utilisent également des opérations unaires qui s'appliquent aux variables. . Ils peuvent être situés soit à gauche, soit à droite d'une variable ; plusieurs opérations de ce type ont déjà été rencontrées - l'opération de déréférencement (*) et la prise d'adresse d'une variable (&) sont unaires. Les opérateurs « ++ » et « — » augmentent et diminuent respectivement la valeur d'une variable entière de 1 et peuvent être écrits soit à gauche, soit à droite de la variable.

C++ utilise également une notation abrégée pour les opérations binaires dans le cas où les côtés gauche et droit d'une expression contiennent la même variable, c'est-à-dire une opération est effectuée sur la valeur d'une variable et le résultat de l'opération est stocké dans la même variable :

UNE += 2; // identique à a = a + 2 ; b /= 5 ; // identique à b = b / 5 ; c & = 3 ; // identique à c = c & 3;

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 short 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 pour 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 sur différentes machines. 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 aux types short 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 d’un pointeur peut changer pendant l’exécution du programme, mais pas la valeur vers laquelle il pointe. */ 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. Plusieurs variables de type énumération peuvent être spécifiées dans une déclaration.

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 ; si les accolades sont manquantes, l'initialisation ne sera pas effectuée correctement.

Dans le langage SI, vous pouvez utiliser des sections de tableau, comme dans d'autres langages de haut niveau (PL1, etc.), cependant, un certain nombre de restrictions sont imposées sur 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 continue.

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 est déclaré avec le mot-clé typedef, l'identifiant à la place de l'objet décrit est le nom du type de données considéré, 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)