Question

C définit au moins 3 niveaux "d'expression constante":

  • expression constante (non qualifiée)
  • expression constante arithmétique
  • expression constante entière

6.6 le paragraphe 3 se lit comme suit:

Les expressions constantes ne doivent pas contenir d'affectation, d'incrémentation, de décrémentation, d'appel de fonction, ou des opérateurs de virgule, sauf lorsqu'ils sont contenus dans une sous-expression qui n'est pas évalué.

Cela signifie-t-il que 1,2 n'est pas une expression constante?

Le paragraphe 8 se lit comme suit:

Une expression de constante arithmétique doit être de type arithmétique et ne doit avoir opérandes qui sont des constantes entières, des constantes flottantes, des constantes d'énumération, des caractères constantes et taille des expressions. Opérateurs de cast dans une expression constante arithmétique doit uniquement convertir les types arithmétiques en types arithmétiques, sauf dans le cadre d'un opérande en opérateur sizeof dont le résultat est une constante entière.

Quels sont les opérandes dans (union { uint32_t i; float f; }){ 1 }.f? Si 1 est l'opérande, alors il s'agit probablement d'une expression constante arithmétique, mais si { 1 } est l'opérande, alors ce n'est clairement pas le cas.

Edit: Une autre observation intéressante: 7.17 paragraphe 3 exige que le résultat de offsetof soit une expression constante entière de type size_t, mais les implémentations standard de offsetof, pour autant que je sache, ne le sont pas requis pour être des expressions constantes entières par la norme. Ceci est bien sûr correct puisqu'une implémentation est autorisée (sous 6.6 paragraphe 10) à accepter d'autres formes d'expressions constantes, ou à implémenter la macro offsetof comme __builtin_offsetof plutôt que via la soustraction de pointeur. L'essence de cette observation, cependant, est que si vous voulez utiliser offsetof dans un contexte où une expression constante entière est requise, vous devez vraiment utiliser la macro fournie par l'implémentation et ne pas lancer la vôtre.

Était-ce utile?

La solution

D'après votre lecture, 1,2 n'est pas une expression constante. Je ne sais pas pourquoi ce n'est pas le cas, mais je suis simplement d'accord avec vous pour dire que ce n'est pas le cas (malgré le fait que cela devrait probablement l'être).

6.5.2 spécifie des littéraux composés comme opérateur de suffixe. Donc dans

(union { uint32_t i; float f; }){ 1 }.f

Les opérandes sont (union { uint32_t i; float f; }){ 1 } et f à l'opérateur .. Ce n'est pas une expression constante arithmétique, puisque le premier argument est un type union, mais c'est une expression constante.

MISE À JOUR: Je me basais sur une interprétation différente de la norme.

Mon raisonnement précédent était que (union { uint32_t i; float f; }){ 1 }.f remplissait les critères d'une expression constante, et était donc une expression constante. Je pense toujours qu'il répond aux critères d'une expression constante (6.6 paragraphe 3) mais qu'il ne s'agit d'aucun des types standard d'expressions constantes (entier, arithmétique ou adresse) et n'est donc soumis qu'à une expression constante par paragraphe 6.6 10, qui autorise les expressions constantes définies par l'implémentation.

J'avais également l'intention d'accéder à votre modification. J'allais affirmer que l'implémentation "hack" de offsetof était une expression constante, mais je pense que c'est la même chose que ci-dessus: elle répond aux critères d'une expression constante (et peut-être une constante d'adresse) mais n'est pas une expression constante entière, et est donc invalide en dehors du paragraphe 6.6 du paragraphe 10.

Autres conseils

Si 1,2 était une expression constante, cela permettrait à un code comme celui-ci de se compiler:

{ // code        // How the compiler interprets:
  int a[10, 10]; // int a[10];

  a[5, 8] = 42;  // a[8] = 42;
}

Je ne sais pas si c'est la vraie raison, mais je peux imaginer qu'émettre une erreur pour cette erreur (courante?) était considéré comme plus important que de transformer 1,2 en une expression constante.

MISE À JOUR : comme R. le souligne dans un commentaire, le code about n'est plus une erreur de compilation depuis l'introduction des VLA.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top