Constante (programmation informatique)
En programmation informatique, une constante est une valeur qui ne doit pas ĂȘtre modifiĂ©e par le programme lors de son exĂ©cution normale, c'est-Ă -dire que la valeur est constante . [note 1] Lorsqu'elle est associĂ©e Ă un identifiant, une constante est dite "nommĂ©e", bien que les termes "constante" et "constante nommĂ©e" soient souvent utilisĂ©s de maniĂšre interchangeable. Cela contraste avec une variable, qui est un identificateur dont la valeur peut ĂȘtre modifiĂ©e pendant l'exĂ©cution normale, c'est-Ă -dire que la valeur est variable. Les constantes sont utiles Ă la fois pour les programmeurs et les compilateurs : pour les programmeurs, elles constituent une forme de code auto-documentĂ© et permettent de raisonner sur l' exactitude, tandis que pour les compilateurs, elles permettent des vĂ©rifications au moment de la compilation et de l'exĂ©cution qui vĂ©rifient que les hypothĂšses de constance ne sont pas violĂ©es, et permettent ou simplifier certaines optimisations du compilateur .
Il existe diverses réalisations spécifiques de la notion générale de constante, avec des distinctions subtiles qui sont souvent négligées. Les plus importantes sont : les constantes de compilation (à valeur statique), les constantes d'exécution (à valeur dynamique), les objets immuables et les types constants ( const ).
Des exemples typiques de constantes de compilation incluent des constantes mathématiques, des valeurs issues de normes (ici unité de transmission maximale ) ou des valeurs de configuration internes (ici caractÚres par ligne ), comme ces exemples C :
const float PI = 3.1415927; // maximal single float precision
const unsigned int MTU = 1500; // Ethernet v2, RFC 894
const unsigned int COLUMNS = 80;
Des exemples typiques de constantes d'exécution sont des valeurs calculées en fonction des entrées d'une fonction, comme cet exemple C++ :
void f(std::string s) {
const size_t l = s.length();
// ...
}
Usage
Certains langages de programmation font une distinction syntaxique explicite entre les symboles constants et variables, par exemple en considérant l'affectation à une constante comme une erreur de syntaxe, tandis que dans d'autres langages, ils sont considérés comme syntaxiquement identiques (tous deux simplement un identifiant), et la différence de traitement est sémantique (l'affectation à un identifiant est syntaxiquement valide, mais si l'identifiant est une constante, il est sémantiquement invalide).
Une valeur constante est dĂ©finie une fois et peut ĂȘtre rĂ©fĂ©rencĂ©e plusieurs fois dans un programme. L'utilisation d'une constante au lieu de spĂ©cifier la mĂȘme valeur plusieurs fois peut simplifier la maintenance du code (comme dans ne vous rĂ©pĂ©tez pas ) et peut s'auto-documenter en fournissant un nom significatif pour une valeur, par exemple, PIâ
au lieu de 3,1415926.
Comparaison avec les littéraux et les macros
Il existe plusieurs façons principales d'exprimer une valeur de données qui ne change pas pendant l'exécution du programme et qui sont cohérentes dans une grande variété de langages de programmation. Une méthode trÚs simple consiste à écrire simplement un nombre littéral, un caractÚre ou une chaßne dans le code du programme, ce qui est simple en C, C++ et autres langages similaires.
En langage d'assemblage, les nombres littéraux et les caractÚres sont effectués à l'aide des instructions de "mode immédiat" disponibles sur la plupart des microprocesseurs. Le nom "immédiat" vient du fait que les valeurs sont disponibles immédiatement à partir du flux d'instructions, au lieu de les charger indirectement en recherchant une adresse mémoire[1]. D'autre part, les valeurs plus longues que la longueur de mot du microprocesseur, telles que les chaßnes et les tableaux, sont traitées indirectement et les assembleurs fournissent généralement une pseudo-opération "données" pour intégrer ces tables de données dans un programme.
Une autre mĂ©thode consiste Ă dĂ©finir une macro symbolique. De nombreux langages de programmation de haut niveau et de nombreux assembleurs offrent une fonction de macro oĂč le programmeur peut dĂ©finir, gĂ©nĂ©ralement au dĂ©but d'un fichier source ou dans un fichier de dĂ©finition sĂ©parĂ©, des noms pour diffĂ©rentes valeurs. Un prĂ©processeur remplace ensuite ces noms par les valeurs appropriĂ©es avant la compilation, ce qui donne quelque chose de fonctionnellement identique Ă l'utilisation de littĂ©raux, avec les avantages de vitesse du mode immĂ©diat. Parce qu'il peut ĂȘtre difficile de maintenir un code oĂč toutes les valeurs sont Ă©crites littĂ©ralement, si une valeur est utilisĂ©e de maniĂšre rĂ©pĂ©titive ou non Ă©vidente, cela se fait souvent comme une macro.
Une troisiĂšme mĂ©thode consiste Ă dĂ©clarer et Ă dĂ©finir une variable comme Ă©tant "constante". Une variable globale ou une variable statique peut ĂȘtre dĂ©clarĂ©e, ce qui signifie que sa valeur sera dĂ©finie au moment de la compilation et ne devrait pas ĂȘtre modifiable au moment de l'exĂ©cution. Les compilateurs placent gĂ©nĂ©ralement des constantes statiques dans la section texte d'un fichier objet avec le code lui-mĂȘme, par opposition Ă la section donnĂ©es oĂč les donnĂ©es initialisĂ©es non const sont conservĂ©es. Certains compilateurs peuvent produire une section spĂ©cifiquement dĂ©diĂ©e aux constantes. La protection de la mĂ©moire peut ĂȘtre appliquĂ©e Ă cette zone pour empĂȘcher l'Ă©crasement de telles constantes par des pointeurs errants.
Ces constantes diffĂšrent des littĂ©raux de plusieurs façons. Les compilateurs placent gĂ©nĂ©ralement une constante dans un seul emplacement de mĂ©moire identifiĂ© par un symbole, plutĂŽt que de la rĂ©partir dans l'exĂ©cutable comme avec une macro. Bien que cela exclut les avantages de vitesse du mode immĂ©diat, il existe des avantages en termes d'efficacitĂ© de la mĂ©moire et les dĂ©bogueurs peuvent travailler avec ces constantes lors de l'exĂ©cution. De mĂȘme, alors que les macros peuvent ĂȘtre redĂ©finies accidentellement par des fichiers d'en-tĂȘte en conflit en C et C++, des constantes en conflit sont dĂ©tectĂ©es au moment de la compilation.
Selon le langage, les constantes peuvent ĂȘtre non typĂ©es ou typĂ©es. En C et C++, les macros fournissent la premiĂšre, tandis que const fournit la seconde :
#define PI 3.1415926535
const float pi2 = 3.1415926535;
tandis qu'en Ada, il existe des types numĂ©riques universels qui peuvent ĂȘtre utilisĂ©s, si vous le souhaitez :
pi : constant := 3.1415926535;
pi2 : constant float := 3.1415926535;
la variante non typée étant implicitement convertie dans le type approprié à chaque utilisation[2].
Constantes Ă valeur dynamique
Outre les constantes statiques dĂ©crites ci-dessus, de nombreux langages procĂ©duraux tels que Ada et C++ Ă©tendent le concept de constance aux variables globales crĂ©Ă©es au moment de l'initialisation, aux variables locales crĂ©Ă©es automatiquement lors de l'exĂ©cution sur la pile ou dans les registres, Ă la mĂ©moire allouĂ©e dynamiquement qui est accessible par un pointeur et aux listes de paramĂštres dans les en-tĂȘtes de fonction.
Les constantes à valeur dynamique ne désignent pas une variable comme résidant dans une région spécifique de la mémoire, et les valeurs ne sont pas définies au moment de la compilation. Dans le code C++ tel que
float func(const float ANYTHING) {
const float XYZ = someGlobalVariable*someOtherFunction(ANYTHING);
...
}
l'expression Ă laquelle la constante est initialisĂ©e n'est pas elle-mĂȘme constante. L'utilisation de la constance n'est pas nĂ©cessaire ici pour la lĂ©galitĂ© du programme ou l'exactitude sĂ©mantique, mais prĂ©sente trois avantages :
- Il est clair pour le lecteur que l'objet ne sera plus modifié, une fois défini
- Les tentatives de modification de la valeur de l'objet (par des programmeurs ultérieurs qui ne comprennent pas entiÚrement la logique du programme) seront rejetées par le compilateur
- Le compilateur peut ĂȘtre en mesure d'effectuer des optimisations de code en sachant que la valeur de l'objet ne changera pas une fois crĂ©Ă©[3].
Les constantes Ă valeur dynamique ont Ă©tĂ© crĂ©Ă©es en tant que fonctionnalitĂ© de langage avec ALGOL 68[3] . Des Ă©tudes sur le code Ada et C++ ont montrĂ© que les constantes Ă valeur dynamique sont rarement utilisĂ©es, gĂ©nĂ©ralement pour 1 % ou moins des objets, alors qu'elles pourraient ĂȘtre utilisĂ©es beaucoup plus, car environ 40 Ă 50 % des objets locaux hors classe sont en fait invariants. une fois crĂ©Ă©[3] - [4]. D'un autre cĂŽtĂ©, ces "variables immuables" ont tendance Ă ĂȘtre la valeur par dĂ©faut dans les langages fonctionnels car elles favorisent les styles de programmation sans effet secondaire (par exemple, la rĂ©cursivitĂ©) ou rendent la plupart des dĂ©clarations immuables par dĂ©faut, comme ML . Les langages purement fonctionnels interdisent mĂȘme complĂštement les effets secondaires.
La constance est souvent utilisĂ©e dans les dĂ©clarations de fonctions, comme une promesse que lorsqu'un objet est passĂ© par rĂ©fĂ©rence, la fonction appelĂ©e ne le changera pas. Selon la syntaxe, un pointeur ou l'objet pointĂ© peut ĂȘtre constant, mais normalement ce dernier est souhaitĂ©. Surtout en C++ et C, la discipline consistant Ă s'assurer que les structures de donnĂ©es appropriĂ©es sont constantes tout au long du programme s'appelle const-correctness .
ParamĂštres de fonction constants
En C/C++, il est possible de dĂ©clarer le paramĂštre d'une fonction ou d'une mĂ©thode comme constante. C'est une garantie que ce paramĂštre ne pourra pas ĂȘtre modifiĂ© aprĂšs la premiĂšre affectation (par inadvertance). Si le paramĂštre est un type prĂ©dĂ©fini (intĂ©grĂ©), il est appelĂ© par valeur et ne peut pas ĂȘtre modifiĂ©. S'il s'agit d'un type dĂ©fini par l'utilisateur, la variable est l'adresse du pointeur, qui ne peut pas non plus ĂȘtre modifiĂ©e. Cependant, le contenu de l'objet peut ĂȘtre modifiĂ© sans limites. DĂ©clarer des paramĂštres comme des constantes peut ĂȘtre un moyen de signaler que cette valeur ne doit pas ĂȘtre modifiĂ©e, mais le programmeur doit garder Ă l'esprit que les vĂ©rifications sur la modification d'un objet ne peuvent pas ĂȘtre effectuĂ©es par le compilateur.
Outre cette fonctionnalitĂ©, il est Ă©galement possible en C++ de dĂ©clarer une fonction ou une mĂ©thode en tant que const . Cela empĂȘche ces fonctions ou mĂ©thodes de modifier autre chose que des variables locales.
En C#, le mot clĂ© const existe, mais n'a pas le mĂȘme effet pour les paramĂštres de fonction, comme c'est le cas en C/C++. Il existe cependant un moyen de "remuer" le compilateur pour effectuer la vĂ©rification, bien que ce soit un peu dĂ©licat[5].
Pour obtenir le mĂȘme effet, d'abord, deux interfaces sont dĂ©finies
public interface IReadable
{
IValueInterface aValue { get; }
}
public interface IWritable : IReadable
{
IValueInterface aValue { set; }
}
public class AnObject : IWritable
{
private ConcreteValue _aValue;
public IValueInterface aValue
{
get { return _aValue; }
set { _aValue = value as ConcreteValue; }
}
}
Ensuite, les méthodes définies sélectionnent la bonne interface avec des capacités de lecture seule ou de lecture/écriture :
public void doSomething(IReadable aVariable)
{
// Cannot modify aVariable!
}
public void doSomethingElse(IWritable aVariable)
{
// Can modify aVariable, so be careful!
}
Constantes orientées objet
Une structure de donnĂ©es ou un objet constant est appelĂ© « immuable » dans le langage orientĂ© objet. Un objet Ă©tant immuable confĂšre certains avantages dans la conception du programme. Par exemple, il peut ĂȘtre "copiĂ©" simplement en copiant son pointeur ou sa rĂ©fĂ©rence, Ă©vitant une opĂ©ration de copie longue et Ă©conomisant de la mĂ©moire.
Les langages orientĂ©s objet tels que C++ Ă©tendent encore plus la constance. Les membres individuels d'une structure ou d'une classe peuvent ĂȘtre rendus const mĂȘme si la classe ne l'est pas. Inversement, le mot clĂ© mutable permet de modifier un membre de classe mĂȘme si un objet a Ă©tĂ© instanciĂ© en tant que const .
MĂȘme les fonctions peuvent ĂȘtre const en C++. La signification ici est que seule une fonction const peut ĂȘtre appelĂ©e pour un objet instanciĂ© en tant que const ; une fonction const ne modifie aucune donnĂ©e non modifiable.
C # a Ă la fois un const et une readonly qualificatif; son const est uniquement pour les constantes de compilation, tandis que readonly peut ĂȘtre utilisĂ© dans les constructeurs et autres applications d'exĂ©cution.
Java
Java a un qualificatif appelĂ© final qui empĂȘche de modifier une rĂ©fĂ©rence et garantit qu'elle ne pointera jamais vers un objet diffĂ©rent. Cela n'empĂȘche pas les modifications de l'objet rĂ©fĂ©rencĂ© lui-mĂȘme. La final de Java est fondamentalement Ă©quivalent Ă un pointeur const en C++. Il ne fournit pas les autres fonctionnalitĂ©s de const .
En Java, la final qualificative indique que le membre de données ou la variable concerné(e) n'est pas attribuable, comme ci-dessous :
final int i = 3;
i = 4; // Error! Cannot modify a "final" object
Il doit ĂȘtre dĂ©cidable par les compilateurs oĂč la variable avec la final marker est initialisĂ© et ne doit ĂȘtre exĂ©cutĂ© qu'une seule fois, sinon la classe ne se compilera pas. La final de Java et les mots-clĂ©s const de C++ ont la mĂȘme signification lorsqu'ils sont appliquĂ©s avec des variables primitives.
const int i = 3; // C++ declaration
i = 4; // Error!
Compte tenu des pointeurs, final fait référence en Java à quelque chose de similaire au pointeur const en C++. En C++, on peut déclarer un "type pointeur constant".
Foo *const bar = mem_location; // const pointer type
Ici, bar doit ĂȘtre initialisĂ© au moment de la dĂ©claration et ne peut plus ĂȘtre changĂ©, mais ce qu'il pointe est modifiable. C'est-Ă -dire que {{{ 1 }}} est valide. Il ne peut tout simplement pas pointer vers un autre emplacement. Les rĂ©fĂ©rences finales en Java fonctionnent de la mĂȘme maniĂšre sauf qu'elles peuvent ĂȘtre dĂ©clarĂ©es non initialisĂ©es.
final Foo i; // a Java declaration
Remarque : Java ne prend pas en charge les pointeurs[6]. C'est parce que les pointeurs (avec des restrictions) sont le moyen par dĂ©faut d'accĂ©der aux objets en Java, et Java n'utilise pas d'Ă©toiles pour les indiquer. Par exemple, i dans le dernier exemple est un pointeur et peut ĂȘtre utilisĂ© pour accĂ©der Ă l'instance. On peut Ă©galement dĂ©clarer un pointeur vers des donnĂ©es "en lecture seule" en C++.
const Foo *bar;
Ici, la barâ
peut ĂȘtre modifiĂ©e pour pointer n'importe quoi, n'importe quand; seule cette valeur pointĂ©e ne peut pas ĂȘtre modifiĂ©e via le pointeur de barâ
.
Il n'existe pas de mĂ©canisme Ă©quivalent en Java. Ainsi, il n'y a pas non plus de mĂ©thodes const . L'exactitude const ne peut pas ĂȘtre appliquĂ©e en Java, bien qu'en utilisant des interfaces et en dĂ©finissant une interface en lecture seule pour la classe et en la transmettant, on peut s'assurer que les objets peuvent ĂȘtre transmis autour du systĂšme de maniĂšre qu'ils ne puissent pas ĂȘtre modifiĂ©s.
Le framework de collections Java fournit un moyen de créer un wrapper immuable d'une [java]et méthodes similaires.
Une mĂ©thode en Java peut ĂȘtre dĂ©clarĂ©e "finale", ce qui signifie qu'elle ne peut pas ĂȘtre remplacĂ©e dans les sous-classes.
C#
En C#, le qualificatif readonly a le mĂȘme effet sur les donnĂ©es membres que final fait en Java et le const fait en C++ ; le modificateur const a un effet similaire (mais typĂ© et de portĂ©e de classe) Ă celui de #define en C++. L'autre effet d'inhibition de l'hĂ©ritage de Java final lorsqu'il est appliquĂ© aux mĂ©thodes et aux classes est induit en C # Ă l'aide du mot-clĂ© sealed .
Contrairement Ă C++, C# ne permet pas aux mĂ©thodes et aux paramĂštres d'ĂȘtre marquĂ©s comme const . Cependant, on peut Ă©galement passer des sous-classes en lecture seule, et le .NET Framework fournit une certaine prise en charge pour la conversion de collections mutables en collections immuables qui peuvent ĂȘtre transmises en tant que wrappers en lecture seule.
Le traitement des constantes varie considérablement selon le paradigme de programmation . L'exactitude const est un problÚme dans les langages impératifs comme C++ car, par défaut, les liaisons de noms créent généralement des variables, qui peuvent varier, comme leur nom l'indique, et donc si l'on souhaite marquer une liaison comme constante, cela nécessite une indication supplémentaire. [note 2] Dans d'autres paradigmes de langage de programmation, des problÚmes liés se posent, avec quelques analogues à la const-exactitude trouvés.
En programmation fonctionnelle, les donnĂ©es sont gĂ©nĂ©ralement constantes par dĂ©faut, plutĂŽt que variables par dĂ©faut. Au lieu d'attribuer une valeur Ă une variable (un espace de stockage avec un nom et une valeur potentiellement variable), on crĂ©e une liaison d'un nom Ă une valeur, comme par la construction letâ
dans de nombreux dialectes en Lisp . Dans certains langages fonctionnels, en particulier ceux multiparadigmes tels que Common Lisp, la modification des donnĂ©es est courante, alors que dans d'autres, elle est Ă©vitĂ©e ou considĂ©rĂ©e comme exceptionnelle ; c'est le cas de Scheme (un autre dialecte Lisp), qui utilise set!â
construire pour modifier les données, avec le! point d'exclamation attirant l'attention sur cela. Ces langages atteignent les objectifs de const-exactitude par défaut, attirant l'attention sur la modification plutÎt que sur la constance.
Dans un certain nombre de langages orientĂ©s objet, il existe le concept d'un objet immuable, qui est particuliĂšrement utilisĂ© pour les types de base comme les chaĂźnes ; les exemples notables incluent Java, JavaScript, Python et C#. Ces langages varient selon que les types dĂ©finis par l'utilisateur peuvent ĂȘtre marquĂ©s comme immuables et peuvent permettre Ă des champs particuliers (attributs) d'un objet ou d'un type d'ĂȘtre marquĂ©s comme immuables.
Dans certains langages multiparadigmes qui autorisent Ă la fois les styles orientĂ©s objet et fonctionnels, ces deux fonctionnalitĂ©s peuvent ĂȘtre combinĂ©es. Par exemple, dans OCaml, les champs d'objet sont immuables par dĂ©faut et doivent ĂȘtre explicitement marquĂ©s avec le mot-clĂ© mutable pour ĂȘtre muables, tandis que dans Scala, les liaisons sont explicitement immuables lorsqu'elles sont dĂ©finies avec valâ
pour "valeur" et explicitement mutables lorsqu'elles sont dĂ©finies avec varâ
pour "variable ".
Conventions de nommage
Les conventions de nommage des constantes varient. Certains les nomment simplement comme ils le feraient pour n'importe quelle autre variable. D'autres utilisent des majuscules et des traits de soulignement pour les constantes d'une maniĂšre similaire Ă leur utilisation traditionnelle pour les macros symboliques, telles que SOME_CONSTANTâ
[7]. En notation hongroise, un préfixe "k" signifie des constantes ainsi que des macros et des types énumérés .
Une convention appliquée est qu'en Ruby, toute variable commençant par une lettre majuscule est considérée comme une constante, y compris les noms de classe.
Notes et références
- (en) Cet article est partiellement ou en totalitĂ© issu de lâarticle de WikipĂ©dia en anglais intitulĂ© « Constant (computer programming) » (voir la liste des auteurs).
Notes
- In some cases the expectation of constancy can be circumvented, e.g. using self-modifying code or by overwriting the memory location where the value is stored.
- This is not universal: in Ada input parameters and loop parameters are implicitly constant, for instance.
Références
- Ex. IBM Systems Information. Instruction Set - Assembler Language Reference for PowerPC.
- Grady Booch, Software Engineering with Ada, Benjamin Cummings, , 116â117 (ISBN 0-8053-0600-5, lire en ligne)
- Schilling, « Dynamically-Valued Constants: An Underused Language Feature », SIGPLAN Notices, vol. 30, no 4,â , p. 13â20 (DOI 10.1145/202176.202177)
- J. A. Perkins « Programming Practices: Analysis of Ada Source Developed for the Air Force, Army, and Navy » (DOI 10.1145/74261.74287)
âProceedings TRI-Ada '89 - Timwi, « Read-only ("const"-like) function parameters of C# », https://stackoverflow.com/, Stack Overflow, (consultĂ© le ) : « [...] Then you can declare methods whose parameter type âtellsâ whether it plans on changing the variable or not:. [...] This mimics compile-time checks similar to constness in C++. As Eric Lippert correctly pointed out, this is not the same as immutability. But as a C++ programmer I think you know that. »
- « Oracle Technology Network for Java Developers | Oracle Technology Network | Oracle », Java.sun.com, (consulté le )
- Microsoft Office XP Developer: Constant Names
Articles connexes
- Constantes d' adresse pour la plate-forme IBM/360 et Z/Architecture