Pourquoi ai-je une erreur lorsque je compare directement deux enums?

J’ai du code que je transfère sur une nouvelle plate-forme et cela a commencé à me donner une erreur lors de la comparaison de deux énumérateurs de deux listes énumératives différentes. Je ne comprends pas pourquoi cela me donne une erreur à ce sujet.

La section des spécificateurs d’énumération de la spécification C (6.7.2.2) indique:

Les identifiants dans une liste d’énumérateurs sont déclarés comme des constantes de type int et peuvent apparaître partout où ils sont autorisés. 127) Un énumérateur avec = définit sa constante d’énumération comme la valeur de l’expression constante. Si le premier énumérateur n’a pas =, la valeur de sa constante d’énumération est 0.

Je devrais donc pouvoir utiliser les membres enum de la même manière que les constantes int. Dans ce petit exemple de programme:

enum first { a, b }; enum second { c, d }; int main(){ enum first myf = a; enum second mys = c; if(myf == mys) printf("same value\n"); return 0; } 

Une fois compilé avec gcc -Wall -Werror je reçois le message suivant:

error: comparaison entre ‘enum first’ et ‘enum second’ [-Werror = enum-compare]

Je sais que si je tape cast à la fois myf et mys tant int le compilateur sera heureux, tout comme je pourrais définir quelques int avec les valeurs de myf et de mys et faire la comparaison; mais pourquoi dois-je faire l’un ou l’autre pour me débarrasser de l’avertissement? Pourquoi cet avertissement existe-t-il en premier lieu? Ce faisant, il doit y avoir un danger que je ne voie pas.


REMARQUE:
J’ai lu la documentation de gcc sur ce drapeau énumération-comparaison, mais cela ne dit pas grand chose:

-Wenum-comparer
Avertir d’une comparaison entre les valeurs de différents types énumérés. En C ++, les incompatibilités énumérées dans les expressions conditionnelles sont également diagnostiquées et l’avertissement est activé par défaut. En C, cet avertissement est activé par -Wall.

Ce n’est pas un avertissement à cause d’un problème de conformité aux normes, c’est un de ces avertissements “cela ne semble pas correct”. Si vous pensez aux utilisations typiques des énumérations, faire une telle comparaison n’a pas beaucoup de sens dans de nombreux cas. Par exemple:

 enum Day { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }; enum Month { January, February, March, April, May, June, July, August, September, October, November, December }; enum Day day = Wednesday; enum Month month = April; if (day == month) { ... } 

Ceci est évalué comme vrai, mais en général, la comparaison n’aurait pas beaucoup de sens. Si vous savez que vous le pensiez, la conversion de type convaincra le compilateur, comme vous l’avez noté.

Il vous avertit parce que le drapeau d’avertissement est activé. La description de l’indicateur n’explique pas pourquoi elle existe, mais il est probablement prudent de supposer qu’elle existe pour éviter les comparaisons accidentelles entre différents types d’énumération, car il s’agit généralement d’ une erreur.

De plus, vous avez raison de dire que vous pouvez utiliser les mêmes valeurs d’énumération que les constantes internationales. Et si vous avez dit if (myf == c) alors il n’aurait probablement pas lancé d’avertissement (je dis très probablement parce que je n’ai pas expérimenté, et GCC peut faire tout ce qu’il veut avec cet avertissement, mais techniquement c est juste une constante intégrale et ne porte pas le type enum second ). Mais au lieu de cela, vous comparez explicitement deux valeurs de types d’énumération différents.

C’est un avertissement, mais comme vous l’avez compilé avec -Wall -Werror, tous les avertissements sont traités comme des erreurs. Reste que vous pouvez trouver quelque chose dans une question similaire.

Existe-t-il un moyen correct d’éviter les avertissements lors de la comparaison de deux énumérations différentes?

cordialement

lui

if((int)myf == (int)mys)

Ça devrait le faire. Mais c’est une mauvaise pratique, ne l’utilisez que si les deux enums sont des “versions” différentes du même groupe, comme si le plus récent en contenait de nouveaux.