Langage C++/Constantes et Variables
Constantes et Variables
modifierEn C++ nous avons besoin, pour pouvoir travailler, d'enregistrer des valeurs en mémoire.
La Mémoire
modifierLa mémoire dans un ordinateur est une succession d'octets (soit 8 bits), organisés les uns à la suite des autres et directement accessibles par une adresse. Ces adresses sont linéaires, et commencent à l'adresse zéro. Certaines de ces adresses sont affectées au matériel (carte graphique, disques durs, BIOS, etc.), les autres servent à enregistrer des données.
Organisation de la mémoire en C++
modifierEn C++ la mémoire est organisée en deux catégories, la pile (de l'anglais Stack) et le Tas (de l'anglais Heap). Cette formalisation vient de l'architecture même des microprocesseurs compatibles i80x86.
La Pile
modifierLa pile est un espace mémoire réservé au stockage des variables désallouées automatiquement en mémoire. Sa taille est limitée mais on peut choisir sa taille de manière à ce que l’on ne la remplisse jamais. Les compilateurs C++ gèrent ce paramétrage et nous n'avons plus à le configurer mais il est important de savoir où sont stockées les variables en mémoire et comment ce processus fonctionne.
La pile est bâtie sur le modèle LIFO (Last In First Out) ce qui signifie littéralement "Dernier Entré Premier Sorti" (DEPS). Il faut voir cet espace mémoire comme une pile d'assiettes où on a le droit d'empiler/dépiler qu'une seule assiette à la fois. Par contre on a le droit d'empiler des assiettes de taille différente. Lorsque l’on ajoute des assiettes on les empile par le haut, les unes au dessus des autres. Quand on les "dépile" on le fait en commençant aussi par le haut, soit par la dernière posée. Lorsqu'une valeur est dépilée elle est effacée de la mémoire.
Description | Adresse | no Élément | Type |
---|---|---|---|
Espace vide de la pile | (vide) | (vide) | (vide) |
Pointeur de pile → | Pile Base + x | n | char |
... | ... | ... | |
Pile Base + 7 | 4 | int (LSB2) | |
Pile Base + 6 | 4 | int (LSB1) | |
Pile Base + 5 | 4 | int (MSB2) | |
Pile Base + 4 | 4 | int (MSB1) | |
Pile Base + 3 | 3 | short(LSB*) | |
Pile Base + 2 | 3 | short(MSB**) | |
Pile Base + 1 | 2 | char | |
Base de la pile → | Pile Base | 1 | char |
* LSB = Least Significant Byte (Octet de Poids Faible)
** MSB = Most Significant Byte (Octet de Poids Fort)
Le Tas
modifierLe tas est l'espace mémoire qui n'est ni alloué au système d'exploitation, ni alloué à la pile du programme. Il est lui aussi limité mais il est aussi beaucoup plus grand que la pile. On lui alloue des valeurs que l’on veut pouvoir transmettre hors des portée des méthodes où elles sont définies. Ne fonctionnant pas comme une pile, la mémoire ainsi allouée doit être désallouée explicitement.
Allocation en Pile et en Tas
modifierAllocation en Pile
modifierUne allocation de valeur en pile se fait grâce au mot clé "auto".
//création d’une variable c de type char désallouée automatiquement à laquelle on affecte la valeur 'A'
auto char c = 'A';
Depuis la normalisation ANSI, il n'est plus nécessaire de préciser le mot clé "auto". Le compilateur génère automatiquement des variables à désallocation automatique.
Ce code est donc équivalent au précédent
Allocation en Tas
modifierPour allouer en tas en C++, il faut utiliser le mot clé "new" qui retourne un pointeur (nous verrons les pointeurs dans un autre chapitre). Après allocation il faut impérativement désallouer le tas sous peine de créer une fuite de mémoire. Pour désallouer une variable en tas, il faut utiliser le mot clé "delete" qui attend comme paramètre un pointeur.
//allocation d’un caractère en tas
char* a = new char;
//affectation de la valeur 'A' à la valeur pointée
*a = 'A';
//désallocation du caractère en tas
delete a;
Attention : L'allocation en tas ne permet pas la désallocation automatique. Chaque allocation de variable créée avec "new" doit impérativement être détruite avec "delete" sous peine de créer une fuite de mémoire. La fuite de mémoire est une zone mémoire qui a été allouée en tas par un programme qui a omis de la désallouer avant de se terminer. Cela rend la zone inaccessible à toute application (y compris le système d'exploitation) jusqu'au redémarrage du système. Si ce phénomène se produit trop fréquemment la mémoire se remplit de fuites et le système finit par tomber faute de mémoire. |
Variables et Constantes
modifierEn C++ il existe deux catégories de valeurs : Les Variables et les Constantes. On peut donc créer en mémoire soit un espace qui contient une valeur variable (ou modifiable), soit un espace qui contient une valeur constante (ou non-modifiable).
Dans le premier cas nous appelons ces espaces mémoire des "variables", dans le second cas nous les appelons des "constantes".
Les Variables
modifierCes espaces mémoire permettent d'enregistrer des valeurs modifiables à volonté. Il n'existe pas de mot clé spécialisé dans la création des variables.
Attention : Une variable non initialisée contient une valeur indéterminée, il est impératif d'initialiser une variable avant toute utilisation afin d’éviter toute erreur de logique. Si vous parvenez à en faire un réflexe vous gagnerez beaucoup de temps sur le débogage. |
Où <Type> correspond au type (de base ou étendu) qui contiendra la valeur constante ou variable <Valeur> et <AutreValeur>, désignée par le nom <NomVariable>. <Type> et <Valeur> doivent être de même nature. <NomVariable> est un identifiant unique répondant aux mêmes critères que les identifiants de constantes.
//exemple de variable du type caractère
char c = 'A';
//exemple de variable du type entier
int i = 2007;
Attention : Certains identifiants sont interdits. Ils sont utilisés par l'environnement de développement et les utiliser provoquera au mieux des erreurs de logique et au pire un plantage général de l'application, pouvant entraîner des instabilités du système. Non seulement la liste est très longue mais elle change en fonction de l'environnement de développement utilisé. Heureusement la plupart des compilateurs avertissent de la mauvaise utilisation de ces identifiants. Si, d'aventure, ils ne le faisaient pas et que vous constatiez des erreurs inexpliquées à l’utilisation d’un identifiant, cela viendrait peut-être d’un problème de conflit de noms d'identifiant. |
Le tableau ci-dessous montre les différentes possibilités pour un nom d'identifiant
Noms d'identifiant | Validité |
---|---|
a | Valide |
R2d2_c6PO_Starwars | Valide |
_a | Valide |
_2 | Valide |
_ | Valide (à éviter) |
-a | Non valide (le "-" est considéré comme l'opérateur mathématique moins) |
248sp542 | Non valide (commence par un chiffre) |
R 2 d 2 | Non valide (il ne doit pas y avoir d'espace) |
Métronome | Non valide (une lettre accentuée n’est pas un caractère autorisé dans un nom d'identifiant) |
Les Constantes
modifierContrairement aux variables les constantes ne peuvent pas être initialisées après leur déclaration et leur valeur ne peut pas être modifiée après initialisation.
Comme cité précédemment, ces espaces mémoire ne peuvent plus être modifiés une fois qu’ils ont été initialisés. Ces constantes doivent être déclarées avec le mot clé "const" et obligatoirement initialisées sur la même ligne.
Où <type> correspond au type (de base ou étendu) qui contiendra la valeur constante <valeur>, désignée par le nom <NomConstante>. <type> et <valeur> doivent être de même nature. <NomConstante> est un identifiant unique composé de caractères alphanumériques sans espace, sans accents et ne commençant pas par un chiffre.
//exemple de constante caractère
const char c = 'A';
//exemple de constante entière
const int i = 2007;
Attention : A l'instar des variables, les constantes ne peuvent pas porter n’importe quel nom d'identifiant. |
Les Constantes Non Nommées
modifierUne constante non nommée est en C++, une catégorie de constante qui n'a pas de nom. En pratique, ce sont des valeurs brutes non modifiables qui ne peuvent pas être représentées autrement.
//exemple de constante caractère non nommée
'A'
//exemple de constante chaîne non nommée
"Une chaine."
//exemple de constante entière non nommée
27
//exemple de constante réelle non nommée
2.6
Exemples :
modifierCes exemples sont très bien pour appréhender le concept de "constante" mais n'ont pas d'autre intérêt fonctionnel.
/*
Création d’une constante nommée "A_MinusculeAccentCirconflexeNumerique", de type "char",
initialisé avec la valeur constante "-125".
*/
const char A_MinusculeAccentCirconflexeNumerique = -125;
/*
Création d’une constante nommée "A_MinusculeAccentCirconflexeAlphanumerique", de type "char",
initialisé avec le caractère constant "â".
*/
const char A_MinusculeAccentCirconflexeAlphanumerique = 'â';
/*
Création d’une constante nommée "E_MajusculeAccentAiguNumerique", de type "unsigned char",
initialisé avec la valeur constante "144".
*/
const unsigned char E_MajusculeAccentAiguNumerique = 144;
/*
Création d’une constante nommée "E_MajusculeAccentAiguAlphanumerique", de type "unsigned char",
initialisé avec le caractère constant "â".
*/
const unsigned char E_MajusculeAccentAiguAlphanumerique = 'É';
/*
Création d’une constante nommée "MaxShort", de type "short",
initialisé avec la valeur constante "32768".
*/
const short MaxShort = 32768;
/*
Création d’une constante nommée "MinShort", de type "short",
initialisé avec la valeur constante "-32767".
*/
const short MinShort = -32767;
/*
Création d’une constante nommée "MaxUnsignedShort", de type "unsigned short",
initialisé avec la valeur constante "65535".
*/
const unsigned short MaxUnsignedShort = 65535;
/*
Création d’une constante nommée "MinUnsignedShort", de type "unsigned short",
initialisé avec la valeur constante "0".
*/
const unsigned short MinUnsignedShort = 0;
/*
Création d’une constante nommée "MaxInt", de type "int",
initialisé avec la valeur constante "2147483648".
*/
const int MaxInt = 2147483648;
/*
Création d’une constante nommée "MinInt", de type "int",
initialisé avec la valeur constante "-2147483647".
*/
const int MinInt = -2147483647;
/*
Création d’une constante nommée "MaxUnsignedInt", de type "unsigned int",
initialisé avec la valeur constante "4294967295".
*/
const unsigned int MaxUnsignedInt = 4294967295;
/*
Création d’une constante nommée "MinUnsignedInt", de type "unsigned int",
initialisé avec la valeur constante "0".
*/
const unsigned int MinUnsignedInt = 0;
Ces exemples sont très bien pour appréhender le concept de "variable" mais n'ont pas d'autre intérêt fonctionnel.
/*
Création d’une variable nommée "A_MinusculeAccentCirconflexeNumerique", de type "char",
initialisé avec la valeur constante numérique "-125".
*/
char A_MinusculeAccentCirconflexeNumerique = -125;
/*
Création d’une variable nommée "A_MinusculeAccentCirconflexeAlphanumerique", de type "char",
non-initialisé.
*/
char A_MinusculeAccentCirconflexeAlphanumerique;
//Initialisation de la variable "A_MinusculeAccentCirconflexeAlphanumerique" avec le caractère constant "â".
A_MinusculeAccentCirconflexeAlphanumerique = 'â';
/*
Création d’une variable nommée "E_MajusculeAccentAiguNumerique", de type "unsigned char",
non-initialisé.
*/
unsigned char E_MajusculeAccentNumerique;
//Initialisation de la variable "E_MajusculeAccentAiguNumerique" avec la valeur constante numérique "144".
E_MajusculeAccentAiguNumerique = 144;
/*
Création d’une variable nommée "A_E_MajusculeAccentAiguAlphanumerique", de type "unsigned char",
initialisé avec le caractère constant "É".
*/
unsigned char E_MajusculeAccentAiguAlphanumerique = 'É';
/*
Création d’une variable nommée "MaxShort", de type "short",
non-initialisé.
*/
short MaxShort;
//Initialisation de la variable "E_MajusculeAccentAiguNumerique" avec la valeur constante numérique "32768".
MaxShort = 32768;
/*
Création d’une variable nommée "MinShort", de type "short",
initialisé avec la valeur constante numérique "-32767".
*/
short MinShort = -32767;
/*
Création d’une variable nommée "MaxUnsignedShort", de type "unsigned short",
initialisé avec la valeur constante numérique "65535".
*/
unsigned short MaxUnsignedShort = 65535;
/*
Création d’une variable nommée "MaxUnsignedShort", de type "unsigned short",
mon-initialisé.
*/
unsigned short MinUnsignedShort;
//Initialisation de la variable "MinUnsignedShort" avec la valeur constante numérique "0".
MinUnsignedShort = 0;
/*
Création d’une variable nommée "MaxInt", de type "int",
mon-initialisé.
*/
int MaxInt;
//Initialisation de la variable "MaxInt" avec la valeur constante numérique "2147483648".
MaxInt = 2147483648;
/*
Création d’une variable nommée "MinInt", de type "int",
initialisé avec la valeur constante numérique "-2147483647".
*/
int MinInt = -2147483647;
/*
Création d’une variable nommée "MaxUnsignedInt", de type "unsigned int",
initialisé avec la valeur constante numérique "4294967295".
*/
unsigned int MaxUnsignedInt = 4294967295;
/*
Création d’une variable nommée "MinUnsignedInt", de type "unsigned int",
initialisé avec la valeur constante numérique "0".
*/
unsigned int MinUnsignedInt = 0;