Article de reference

const (programmation informatique)

Dans certains langages de programmation , `const` est un qualificateur de type (un mot-clé appliqué à un type de données ) indiquant que les données sont en lecture seule. Bien ...

langages de programmation , `const` est un qualificateur de type (un mot-clé appliqué à un type de données ) indiquant que les données sont en lecture seule. Bien que ce qualificateur puisse servir à déclarer des constantes , famille de langages C, il diffère des constructions similaires d'autres langages en ce qu'il fait partie intégrante du type et présente donc un comportement complexe lorsqu'il est combiné avec des pointeurs , des références, des types de données composites et la vérification de types . Dans d'autres langages, les données ne sont pas stockées à un emplacement mémoire unique , mais copiées à la compilation pour chaque utilisation. Parmi les langages qui l'utilisent, on peut citer C , C++ , D , JavaScript , Julia et Rust .

la déclaration d'un objet , indique que l'objet est une constante : sa valeur ne peut pas être modifiée, contrairement à une variable . Cet usage fondamental – déclarer des constantes – se retrouve dans de nombreux autres langages.

Cependant, contrairement à d'autres langages, dans la famille des langages C, le type constfait partie du type , et non de l' objet . Par exemple, en C, déclare un objet de type `int` – le type fait partie du type, comme s'il était interprété comme « (const int) x » – tandis qu'en Ada , déclare une constante (une sorte d'objet) de type `int` : le type fait partie de l' objet , mais pas du type .correction de programme , appelée correction par constante . Elle permet une programmation par contrat , où les fonctions spécifient, dans leur signature de type , si elles modifient leurs arguments et si leur valeur de retour est modifiable. Cette vérification de type est principalement pertinente pour les pointeurs et les références – et non pour les types valeur de base comme les entiers – mais aussi pour les types de données composites ou les types paramétrés tels que les conteneurs . Elle est masquée par le fait que `__init__` constpeut souvent être omis, grâce à la coercition de type ( conversion de type implicite ) et au fait que le C utilise le passage par valeur (le C++ et le D utilisent soit le passage par valeur, soit le passage par référence).

Conséquences

La notion de constance n'implique pas que la variable, telle qu'elle est stockée en mémoire, soit inaltérable. constIl s'agit plutôt d'une construction de compilation indiquant ce que le programmeur doit faire, et non nécessairement ce qu'il peut faire. Notez cependant que, dans le cas de données prédéfinies (comme const char*les chaînes de caractères littérales ), le C constest souvent inaltérable.

Distinction par rapport aux constantes

Alors qu'une constante ne change pas de valeur pendant l'exécution du programme, un objet déclaré constpeut, lui, voir sa valeur modifiée. Un exemple courant est celui des registres en lecture seule dans les systèmes embarqués, comme l'état actuel d'une entrée numérique. Les registres de données des entrées numériques sont souvent déclarés comme `int` constet `int` volatile. Le contenu de ces registres peut changer sans intervention du programme (`int` volatile), mais il serait incorrect que le programme tente d'y écrire (`int` const).

Autres utilisations

De plus, une fonction membre (non statique) peut être déclarée comme `const` const. Dans ce cas, le thispointeur à l'intérieur de cette fonction est de type `const` const T*plutôt que simplement de type `int` T*. Cela signifie que les fonctions non constantes de cet objet ne peuvent pas être appelées depuis l'intérieur de cette fonction, et que les variables membres ne peuvent pas être modifiées. En C++, une variable membre peut être déclarée comme `const` mutable, indiquant que cette restriction ne s'applique pas à elle. Dans certains cas, cela peut être utile, par exemple pour la mise en cache , le comptage de références et la synchronisation des données . Dans ces cas, la signification logique (l'état) de l'objet reste inchangée, mais l'objet n'est pas physiquement constant puisque sa représentation binaire peut changer.

Syntaxe

En C, C++ et D, tous les types de données, y compris ceux définis par l'utilisateur, peuvent être déclarés const`const`. La norme `const` impose que toutes les variables et tous les objets soient déclarés comme tels, sauf s'ils doivent être modifiés. Cette utilisation proactive de const`const` rend les valeurs plus faciles à comprendre, à suivre et à interpréter , améliorant ainsi la lisibilité et la compréhensibilité du code. Elle simplifie également le travail en équipe et la maintenance du code, car elle communique des informations sur l'utilisation prévue d'une valeur. Ceci peut aider le compilateur et le développeur lors de l'interprétation du code. Cela peut également permettre à un compilateur optimisant de générer un code plus efficace

Types de données simples

Pour les types de données simples non pointeurs, l'application du constqualificateur est directe. Il peut être placé indifféremment avant ou après certains types pour des raisons historiques (par exemple, `is` const char foo = 'a';est équivalent à ` char const foo = 'a';is`). Sur certaines implémentations, son utilisation constdeux fois (par exemple, ` const char constis` ou ` char const constis`) génère un avertissement, mais pas d'erreur.

Conseils et références

Pour les types pointeur et référence, la signification de `void` constest plus complexe : `void` peut désigner soit le pointeur lui-même, soit la valeur pointée, soit les deux const. De plus, la syntaxe peut prêter à confusion. Un pointeur peut être déclaré comme un constpointeur vers une valeur accessible en écriture, ou un pointeur accessible en écriture vers une constvaleur, ou encore constun pointeur vers constune valeur.pointée ). Les variables de référence en C++ constituent une syntaxe alternative pour constles pointeurs. Un pointeur vers un constobjet, en revanche, peut être réaffecté pour pointer vers une autre adresse mémoire (qui doit être un objet du même type ou d'un type convertible), mais il ne peut pas être utilisé pour modifier la mémoire pointée. Un constpointeur vers un constobjet peut également être déclaré et ne peut ni être utilisé pour modifier la pointée ni être réaffecté pour pointer vers un autre objet. Le code suivant illustre ces subtilités :

le déréférencement . Par exemple, dans la déclaration `d` int *p, la forme déréférencée *pest un `int` int, tandis que la forme de référence pest un pointeur vers un `int` int. Ainsi, ` constd` modifie le nom à sa droite. La convention C++ consiste plutôt à associer le ` *d` au type, comme dans `d` int* p, et à lire le `d` constcomme modifiant le type à sa gauche. ` const int * cpd` peut donc être lu comme « *cpest un const int`int` » (la valeur est constante), ou comme « cpest un const int *`int` » (le pointeur est un pointeur vers un entier constant). Ainsi :

règle générale est de lire la déclaration de droite à gauche. Ainsi, tout ce qui se trouve à gauche de l'astérisque correspond au type pointé, et tout ce qui se trouve à droite correspond aux propriétés du pointeur. Par exemple, dans notre exemple ci-dessus, `int` const int*peut être lu comme un pointeur accessible en écriture qui référence un entier non accessible en écriture, et ` int* constint` comme un pointeur non accessible en écriture qui référence un entier accessible en écriture.

Une règle plus générale pour faciliter la compréhension des déclarations et définitions complexes fonctionne comme suit :

  1. trouver l'identifiant de la déclaration en question
  2. lire aussi loin que possible vers la droite (c'est-à-dire jusqu'à la fin de la déclaration ou jusqu'à la prochaine parenthèse fermante, selon ce qui arrive en premier).
  3. Revenez à l'endroit où la lecture a commencé et lisez à rebours vers la gauche (c'est-à-dire jusqu'au début de la déclaration ou jusqu'à la parenthèse ouvrante correspondant à la parenthèse fermante trouvée à l'étape précédente).
  4. Une fois arrivé au début de la déclaration, terminez. Sinon, reprenez à l'étape 2, après la parenthèse fermante précédemment appariée.

Voici un exemple :

C# , l'alignement à droite de l'astérisque est illégal.

statiques ou automatiques, globales ou locales). Son interprétation varie selon le contexte. Une variable statique ( constglobale ou locale statique ) est une constante et peut servir à stocker des données telles que des constantes mathématiques, par exemple `a`, `b`, `c` , ` c`, `d`, `e ...const double PI = 3.14159constconst int x_squared = x * xconstconstconst

C++

En C++, il existe quatre types différents de constexpr )

  • de conception par contrat pour les types définis par l'utilisateur (structures et classes), qui peuvent comporter des méthodes et des données membres, le programmeur peut déclarer les méthodes d'instance comme constne modifiant pas les membres de données de l'objet. L'application du constqualificateur aux méthodes d'instance est donc essentielle pour garantir la constance et n'est pas disponible dans de nombreux autres langages orientés objet tels que Java et C# , ni dans C++/CLI ou les extensions gérées pour C++ de Microsoft . Si les méthodes peuvent être appelées par des objets et des non- objets, les méthodes non-objets ne peuvent être invoquées que par des non- objets. Le modificateur d'une méthode d'instance s'applique à l'objet pointé par le pointeur implicite « », qui est un argument implicite passé à toutes les méthodes d'instance. Ainsi, la présence de méthodes permet d'appliquer la constance à l' argument implicite « pointeur », au même titre que les autres arguments.constconstconstconstconstconstthisconstthis

    Cet exemple illustre :

    void set ( int j ) noexcept { i = j ; } };void foo ( Integer & nonConstInteger , const Integer & constInteger ) { int y = nonConstInteger.get ( ); // OK int x = constInteger.get ( ); // OK : get() est constantnonConstInteger.set ( 10 ); // OK : nonConstInteger est modifiable constInteger.set ( 10 ); // Erreur ! set ( ) est une méthode non constante et constInteger est un objet qualifié const }

    Dans le code ci-dessus, le thispointeur implicite " " vers set()a le type " Integer* const"; tandis que le thispointeur " " vers get()a le type " Integer const* const", indiquant que la méthode ne peut pas modifier son objet via le thispointeur " ".

    Souvent, le programmeur fournira dans une classe à la fois une méthode `a` constet une constméthode `non-a` portant le même nom (mais pouvant avoir des usages très différents) afin de convenir aux deux types d'appelants. Par exemple :

    bibliothèque de modèles standard .)

  • Failles à la correction constante

    Il existe plusieurs failles dans la garantie d'une correction stricte des constantes en C et C++. Elles existent principalement pour des raisons de compatibilité avec le code existant.

    La première, qui s'applique uniquement au C++, est l'utilisation de `const` const_cast, qui permet au programmeur de supprimer le constqualificateur `const`, rendant ainsi tout objet modifiable. La nécessité de supprimer le qualificateur `const` se présente lors de l'utilisation de code existant et de bibliothèques non modifiables mais qui ne sont pas `const`. Par exemple, considérons ce code :

    constante entraîne un comportement indéfini selon la norme ISO C++. Dans l'exemple ci-dessus, si ` ptrthis` fait référence à une variable globale, locale ou membre déclarée comme `const` const, ou à un objet alloué sur le tas via `const` new int const, le code est correct uniquement si LibraryFunc`this` ne modifie pas la valeur pointée par `this` ptr.

    Le langage C présente une lacune nécessaire en raison d'une situation particulière. Les variables à durée de vie statique peuvent être initialisées. Cependant, l'initialiseur ne peut utiliser que des constantes, comme les chaînes de caractères et autres littéraux, et ne peut contenir d'éléments non constants tels que des noms de variables, que les éléments de l'initialiseur soient déclarés constou non, ou que la variable à durée de vie statique soit déclarée constou non. Il existe une méthode non portable pour initialiser une constvariable à durée de vie statique. En effectuant une conversion de type avec soin à gauche d'une affectation ultérieure, constil est possible d'écrire dans une variable, ce qui revient à supprimer l' constattribut et à l'« initialiser » avec des éléments non constants, comme d'autres constvariables. constBien que cette méthode puisse fonctionner comme prévu, elle engendre un comportement indéfini et contredit sérieusement le principe de constance.

    bibliothèque standard C violent la propriété de constance avant C23 , car elles acceptent un constpointeur vers une chaîne de caractères et renvoient une constvaleur non constance vers une partie de cette même chaîne. strstret strchrfont partie de ces fonctions. Certaines implémentations de la bibliothèque standard C++, comme celle de Microsoft tentent de combler cette lacune en fournissant deux versions surchargées de certaines fonctions : une constversion « const » et une constversion « non-const ».

    Problèmes

    signature de type de ces fonctions étant différente, il est nécessaire de créer deux fonctions (voire plus, en cas d'entrées multiples) ayant la même logique : c'est une forme de programmation générique .

    Ce problème se pose même pour des fonctions simples de la bibliothèque standard C, notammentstrchr ; cette observation est attribuée par Ritchie à Tom Plum au milieu des années 1980. La strchrfonction localise un caractère dans une chaîne ; formellement, elle renvoie un pointeur vers la première occurrence du caractère cdans la chaîne s, et en C classique (K&R C), son prototype est :

    surcharge de fonctions , généralement implémentée via un modèle , ce qui donne deux fonctions, de sorte que la valeur de retour ait le même consttype qualifié que l'entrée :

    la sécurité des types . Cette solution a été proposée par Ritchie et adoptée par la suite. Cette différence constitue l'un des problèmes de compatibilité entre C et C++ .

    Depuis C23 , ce problème est résolu grâce à une _Genericfonctionnalité du langage : les identificateurs de strchret des autres fonctions concernées par le problème ont été transformés en macros qui développent un appel à une fonction appropriée qui renverra un constpointeur si un pointeur lui a été passé et un pointeur non qualifié si un pointeur non qualifié lui a été passé.

    D

    Dans la version 2 du langage de programmation D , deux mots-clés relatifs à la constante existent. Le immutablemot-clé `const` désigne des données qui ne peuvent être modifiées par aucune référence. Le constmot-clé `const` désigne une vue non mutable de données mutables. Contrairement à C++ const, en D, `const` constet ` immutableconst` sont « profonds » ou transitifs ; tout ce qui est accessible via un objet const`const` ou `const` est respectivement `const` ou ` const`.immutableconstimmutable

    Exemple de const vs. immutable en D

    Bjarne Stroustrup dans C with Classes , le prédécesseur de C++ , en 1981, et s'appelait à l'origine readonly. Quant à la motivation, Stroustrup écrit :

    « Cela remplissait deux fonctions : définir une constante symbolique qui obéit aux règles de portée et de type (c’est-à-dire sans utiliser de macro) et déclarer un objet en mémoire immuable. »

    La première utilisation, en tant qu'alternative à portée et typée aux macros, a été réalisée de manière analogue pour les macros de type fonction via le inlinemot-clé. Les pointeurs constants et la * constnotation ont été suggérés par Dennis Ritchie et ont donc été adoptés.

    consta ensuite été adopté en C dans le cadre de la normalisation et apparaît dans C89 (et les versions ultérieures) avec l'autre qualificateur de type, volatile. Un qualificateur supplémentaire, noalias, a été proposé lors de la réunion de décembre 1987 du comité X3J11, mais a été rejeté ; son objectif a finalement été atteint par le restrictmot-clé dans C99 . Ritchie n'était pas très favorable à ces ajouts, arguant qu'ils n'étaient pas « justifiés », mais n'a finalement pas plaidé pour leur suppression de la norme.

    D a ensuite hérité constdu C++, où il est connu comme un constructeur de type (et non comme un qualificateur de type ), et a ajouté deux autres constructeurs de type, immutableet inout, pour gérer des cas d'utilisation connexes.

    Autres langues

    D'autres langages, contrairement à C/C++, n'intègrent pas la constance dans le type, bien qu'ils proposent souvent des constructions superficiellement similaires et puissent utiliser le constmot-clé `constant`. Généralement, ce dernier est réservé aux constantes (objets constants).

    En C# , il existe un constmot-clé `const`, mais sa sémantique est radicalement différente et plus simple : il désigne une constante de compilation et ne fait pas partie du type. Il est essentiellement équivalent à `const` constexpren C et C++.

    Nim possède un constmot-clé similaire à celui de C# : il permet également de déclarer une constante de compilation plutôt que de l’intégrer au type. Cependant, en Nim, une constante peut être déclarée à partir de n’importe quelle expression évaluable à la compilation. En C#, seuls les types intégrés peuvent être déclarés de cette manièreconst ; les types définis par l’utilisateur, tels que les classes, les structures et les tableaux, ne le peuvent pas const.

    Rust possède un constmot-clé similaire à celui de C#, qui déclare les constantes, les fonctions et autres symboles à la compilation. Il est donc essentiellement équivalent à constexprcelui de C et C++.

    Java n'utilise pas const`__init__`, mais `__init__` final, qui peut être appliqué aux déclarations de « variables » locales et s'applique à l' identificateur , et non au type. Son utilisation pour les membres d'objets est différente, d'où son nom. La spécification du langage Java considère `__init__` constcomme un mot-clé réservé – c'est-à-dire un mot-clé qui ne peut pas être utilisé comme identificateur de variable – mais ne lui attribue aucune sémantique : c'est un mot réservé (il ne peut pas être utilisé dans les identificateurs) mais pas un mot-clé (il n'a pas de signification particulière). Le mot-clé `__init__` a été inclus pour permettre aux compilateurs Java de détecter et de signaler l'utilisation incorrecte des mots-clés C++. Une demande d'amélioration visant à corriger const`__init__` existe dans le Java Community Process , mais elle a été fermée en 2005 car il était impossible de l'implémenter de manière rétrocompatible.

    La version contemporaine d'Ada 83 intégrait indépendamment la notion d'objet constant et le constantmot-clé , les paramètres d'entrée et de boucle étant implicitement constants. Ici, il constants'agit d'une propriété de l'objet, et non du type.

    JavaScript possède une constdéclaration qui définit une variable de portée bloc qui ne peut être ni réassignée ni redéclarée. Elle définit une référence en lecture seule à une variable qui ne peut être redéfinie, mais dans certaines situations, la valeur de la variable elle-même peut potentiellement changer, par exemple si la variable fait référence à un objet et qu'une propriété de celui-ci est modifiée.

    Plus d articles de Worldlex Wiki

    Revenez a l index pour explorer davantage de pages sur l histoire, la science, la culture, la geographie et la societe en francais.

    Explorer l index