Namespaces
Variants

Value categories

From cppreference.net

Chaque expression en C (un opérateur avec ses arguments, un appel de fonction, une constante, un nom de variable, etc.) est caractérisée par deux propriétés indépendantes : un type et une catégorie de valeur .

Chaque expression appartient à l'une des trois catégories de valeurs : lvalue, objet non-lvalue (rvalue) et désignateur de fonction.

Table des matières

Expressions lvalue

Une expression lvalue est toute expression ayant un type objet autre que le type void , qui désigne potentiellement un objet (le comportement est indéfini si une lvalue ne désigne pas réellement un objet lors de son évaluation). En d'autres termes, une expression lvalue s'évalue en l'identité de l'objet  . Le nom de cette catégorie de valeur ("valeur gauche") est historique et reflète l'utilisation des expressions lvalue comme opérande gauche de l'opérateur d'affectation dans le langage de programmation CPL.

Les expressions lvalue peuvent être utilisées dans les contextes lvalue  suivants :

Si une expression lvalue est utilisée dans tout contexte autre que sizeof , _Alignof , ou les opérateurs mentionnés ci-dessus, les lvalues non-tableaux de tout type complet subissent une conversion lvalue , qui modélise le chargement en mémoire de la valeur de l'objet depuis son emplacement. De même, les lvalues de tableau subissent une conversion tableau-vers-pointeur lorsqu'elles sont utilisées dans tout contexte autre que sizeof , _Alignof , l'opérateur d'adresse, ou l'initialisation d'un tableau à partir d'un littéral de chaîne.

La sémantique des const / volatile / restrict -qualificateurs et des types atomiques s'applique uniquement aux lvalues (la conversion lvalue supprime les qualificateurs et retire l'atomicité).

Les expressions suivantes sont des lvalues :

  • identifiants, y compris les paramètres nommés de fonctions, à condition qu'ils aient été déclarés comme désignant des objets (pas des fonctions ou des constantes d'énumération)
  • littéraux de chaîne
  • (C99) littéraux composés
  • expression entre parenthèses si l'expression sans parenthèses est une lvalue
  • résultat d'un opérateur d'accès membre (point) si son argument gauche est une lvalue
  • résultat d'un accès membre via pointeur -> opérateur
  • résultat de l'opérateur d'indirection (unaire * ) appliqué à un pointeur vers un objet
  • résultat de l'opérateur de subscriptage ( [] )

Expressions lvalue modifiables

Une lvalue modifiable est toute expression lvalue de type complet non-tableau qui n'est pas const -qualifiée, et, s'il s'agit d'une structure/union, n'a aucun membre const -qualifié, récursivement.

Seules les expressions lvalue modifiables peuvent être utilisées comme arguments pour l'incrément/décrément, et comme opérandes gauche des opérateurs d'affectation et d'affectation composée.

Expressions d'objet non-lvalue

Connues sous le nom de rvalues  , les expressions d'objets non-lvalue sont les expressions de types d'objets qui ne désignent pas des objets, mais plutôt des valeurs qui n'ont pas d'identité d'objet ou d'emplacement de stockage. L'adresse d'une expression d'objet non-lvalue ne peut pas être prise.

Les expressions suivantes sont des expressions d'objet non-lvalue :

  • constantes entières, caractères et flottantes
  • tous les opérateurs non spécifiés comme retournant des lvalues, incluant
  • toute expression d'appel de fonction
  • toute expression de conversion (notez que les littéraux composés, qui semblent similaires, sont des lvalues)
  • opérateur d'accès membre (point) appliqué à une structure/union non lvalue, f ( ) . x , ( x, s1 ) . a , ( s1 = s2 ) . m
  • résultats de tous les opérateurs arithmétiques, relationnels, logiques et bit à bit
  • résultats des opérateurs d'incrément et de décrément (note : les formes préfixées sont des lvalues en C++)
  • résultats des opérateurs d'affectation (note : également des lvalues en C++)
  • l'opérateur conditionnel (note : est une lvalue en C++ si les deuxième et troisième opérandes sont des lvalues du même type)
  • l'opérateur virgule (note : est une lvalue en C++ si le deuxième opérande l'est)
  • l'opérateur d'adresse, même s'il est neutralisé par l'application au résultat de l'opérateur unaire *

En tant que cas particulier, les expressions de type void sont considérées comme des expressions d'objet non-lvalue qui produisent une valeur sans représentation et ne nécessitant aucun stockage.

Notez qu'une valeur de struct/union qui possède un membre (éventuellement imbriqué) de type tableau désigne en fait un objet avec durée de vie temporaire . Cet objet peut être accédé via des expressions lvalue qui se forment en indexant le membre tableau ou par indirection via le pointeur obtenu par conversion tableau-vers-pointeur du membre tableau.

(depuis C99)

Expression de désignateur de fonction

Un désignateur de fonction (l'identificateur introduit par une déclaration de fonction ) est une expression de type fonction. Lorsqu'il est utilisé dans tout contexte autre que l'opérateur d'adresse, sizeof , et _Alignof (les deux derniers génèrent des erreurs de compilation lorsqu'ils sont appliqués à des fonctions), le désignateur de fonction est toujours converti en un pointeur non-lvalue vers fonction. Notez que l'opérateur d'appel de fonction est défini pour les pointeurs vers fonctions et non pour les désignateurs de fonction eux-mêmes.

Références

  • Norme C23 (ISO/CEI 9899:2024) :
  • 6.3.2.1 Lvalues, tableaux et désignateurs de fonction (p: 48-49)
  • Norme C17 (ISO/CEI 9899:2018) :
  • 6.3.2.1 Lvalues, tableaux et désignateurs de fonction (p: 40)
  • Norme C11 (ISO/CEI 9899:2011) :
  • 6.3.2.1 Lvalues, tableaux et désignateurs de fonction (p: 54-55)
  • Norme C99 (ISO/CEI 9899:1999) :
  • 6.3.2.1 Lvalues, tableaux et désignateurs de fonction (p: 46)
  • Norme C89/C90 (ISO/CEI 9899:1990) :
  • 3.2.2.1 Lvalues et désignateurs de fonction

Voir aussi

Documentation C++ pour Catégories de valeur