Namespaces
Variants

Constant expressions

From cppreference.net

Plusieurs variétés d'expressions sont connues sous le nom d' expressions constantes .

Table des matières

Expression constante du préprocesseur

L'expression suivant #if ou #elif doit s'étendre à

Les constantes de caractères, lorsqu'elles sont évaluées dans des #if -expressions, peuvent être interprétées dans le jeu de caractères source, le jeu de caractères d'exécution, ou un autre jeu de caractères défini par l'implémentation.

L'arithmétique entière dans les expressions #if est réalisée en utilisant la sémantique de intmax_t pour les types signés et uintmax_t pour les types non signés.

(depuis C99)

Expression constante entière

Une expression constante entière est une expression qui se compose uniquement de

  • _Alignof (jusqu'en C23) alignas (depuis C23) opérateurs
(depuis C11)
  • constantes littérales nommées et composées qui sont de type entier ou qui sont de type arithmétique et sont les opérandes immédiats de conversions
(depuis C23)

Les expressions constantes entières sont évaluées à la compilation. Les contextes suivants requièrent des expressions connues sous le nom d' expressions constantes entières :

(depuis C99)
(depuis C11)
  • Le nombre de bits N d'un type entier à précision de bits ( _BitInt ( N ) )
(depuis C23)

Initialiseur statique

Les expressions utilisées dans les initialiseurs des objets ayant une durée de stockage statique et thread_local ou déclarés avec le spécificateur de classe de stockage constexpr (depuis C23) doivent être soit des littéraux de chaîne, soit des expressions pouvant être l'une des suivantes

1) expression constante arithmétique , qui est une expression de tout type arithmétique constituée de
(depuis C11)
  • constantes littérales nommées ou composées de type arithmétique
(depuis C23)
2) une constante de pointeur nul (par exemple, NULL ).
3) expression constante d'adresse , qui est
  • en utilisant l'opérateur unaire d'adresse
  • en convertissant une constante entière en pointeur
  • par conversion implicite tableau-vers-pointeur ou fonction-vers-pointeur conversion .
4) expression constante d'adresse d'un type d'objet complet, plus ou moins une expression constante entière .
5) une constante nommée qui est, un identifiant qui est
  • une constante d'énumération
  • une constante prédéfinie (l'une de true , false ou nullptr )
  • déclaré avec le spécificateur de classe de stockage constexpr et a un type objet
ou une expression postfixée qui applique l'opérateur d'accès membre . à une constante nommée de type structure ou union, même récursivement.
6) une constante littérale composée , qui est
  • un littéral composé avec le spécificateur de classe de stockage constexpr
  • une expression postfixée qui applique l'opérateur d'accès membre . à une constante littérale composée de type structure ou union, même récursivement.

Une constante de structure ou d'union est respectivement une constante nommée ou une constante littérale composée de type structure ou union. Si l'opérateur d'accès membre . accède à un membre d'une constante d'union, le membre accédé doit être le même que le membre qui est initialisé par l'initialiseur de la constante d'union.

(depuis C23)
7) expression constante de l'une des autres formes acceptées par l'implémentation.

Contrairement aux expressions constantes entières, les expressions d'initialiseur statique ne sont pas tenues d'être évaluées à la compilation ; le compilateur a la liberté de transformer ces initialiseurs en code exécutable qui est invoqué avant le démarrage du programme.

static int i = 2 || 1 / 0; // initialise i à la valeur 1

La valeur d'un initialiseur statique de type à virgule flottante n'est jamais moins précise que la valeur de la même expression exécutée à l'exécution, mais elle peut être meilleure.

Expressions constantes à virgule flottante

Les expressions constantes arithmétiques de types à virgule flottante qui ne sont pas utilisées dans des initialiseurs statiques sont toujours évaluées comme si elles l'étaient pendant l'exécution et sont affectées par la méthode d'arrondi courante (si FENV_ACCESS est activé) et signalent les erreurs comme spécifié dans math_errhandling .

void f(void)
{
#pragma STDC FENV_ACCESS ON
    static float x = 0.0 / 0.0; // initialiseur statique : ne lève pas d'exception
    float w[] = { 0.0 / 0.0 };  // lève une exception
    float y = 0.0 / 0.0;        // lève une exception
    double z = 0.0 / 0.0;       // lève une exception
}

Notes

Si une expression évalue à une valeur qui n'est pas représentable par son type, elle ne peut pas être utilisée comme expression constante.

Les implémentations peuvent accepter d'autres formes d'expressions constantes. Cependant, ces expressions constantes ne sont pas considérées comme des expressions constantes entières, des expressions constantes arithmétiques ou des expressions constantes d'adresse, et ne peuvent donc pas être utilisées dans les contextes nécessitant ces types d'expressions constantes. Par exemple, int arr [ ( int ) + 1.0 ] ; déclare un VLA.

Références

  • Norme C23 (ISO/CEI 9899:2024) :
  • 6.6 Expressions constantes (p: 95-96)
  • Norme C17 (ISO/CEI 9899:2018):
  • 6.6 Expressions constantes (p: 76-77)
  • Norme C11 (ISO/IEC 9899:2011) :
  • 6.6 Expressions constantes (p: 106-107)
  • Norme C99 (ISO/CEI 9899:1999) :
  • 6.6 Expressions constantes (p: 95-96)
  • Norme C89/C90 (ISO/IEC 9899:1990) :
  • 3.4 EXPRESSIONS CONSTANTES

Voir aussi

Documentation C++ pour Expressions constantes