Why do I get an error when directly comparing two

2020-07-03 04:56发布

问题:

I have some code I'm porting to a new platform, and it started giving me an error about comparing two enumerators from two different enumerator-lists. I'm confused why it's giving me an error about this.

The enumeration specificers section of the C spec (6.7.2.2) states:

The identifiers in an enumerator list are declared as constants that have type int and may appear wherever such are permitted.127) An enumerator with = defines its enumeration constant as the value of the constant expression. If the first enumerator has no =, the value of its enumeration constant is 0.

So I should be able to use enum members the same as int constants. In this small sample program:

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;
}

When compiled with gcc -Wall -Werror I get the message:

error: comparison between ‘enum first’ and ‘enum second’ [-Werror=enum-compare]

I know that if I typecast both myf and mys as ints the compiler will be happy, just like I could set a couple of ints with the values from myf and mys and do the comparison; but why do I have to do either of these to get rid of the warning? Why does this warning exist in the first place? There must be some danger in doing this that I'm not seeing.


NOTE:
I have read the gcc documentation on this enum-compare flag, but it doesn't say much of anything:

-Wenum-compare
Warn about a comparison between values of different enumerated types. In C++ enumeral mismatches in conditional expressions are also diagnosed and the warning is enabled by default. In C this warning is enabled by -Wall.

回答1:

This isn't a warning because of a standards compliance issue, it's one of those "this doesn't seem right" kind of warnings. If you think of the typical uses of enums, doing such a comparison doesn't make much sense in many cases. For example:

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) { ... }

This evaluates to true, but in general the comparison wouldn't make much sense. If you know you meant it, the typecast will convince the compiler, as you noted.



回答2:

It's warning you because you have the warning flag on. The flag description doesn't explain why it exists, but it's probably safe to assume that it exists to prevent accidental comparisons between different enumeration types, because this usually is an error.

Furthermore, you are correct that you can use enumeration values the same as you can int constants. And if you said if (myf == c) then it most likely wouldn't have thrown a warning (I say most likely because I haven't experimented, and GCC honestly can do whatever it wants with that warning, but technically c is just an integral constant and does not carry the type enum second). But instead you're explicitly comparing two values of different enumeration types.



回答3:

Its a warning but as you have compiled with -Wall -Werror all warnings are treated as error Rest you can find something in similar question.

Is there a correct way to avoid warnings when comparing two different enums?

with regards

hims



回答4:

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

That should do it. But it is dirty practice, only use it if both enums are different "versions" of the same group, like the newer one would contain new keywords at the end.