2013-04-02 21 views
11

Mam pewien kod, który przesyłam na nową platformę, i zaczęto podawać mi błąd dotyczący porównywania dwóch enumeratorów z dwóch różnych list wyliczeniowych. Jestem zdezorientowany, dlaczego daje mi to błąd.Dlaczego pojawia się błąd podczas bezpośredniego porównywania dwóch wyliczeń?

wyliczenia specificers odcinek spec C (6.7.2.2) stwierdza:

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.

Więc powinienem być w stanie wykorzystać członków enum tak samo jak int stałych. W tym małym programem próbki:

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

Kiedy skompilowany z gcc -Wall -Werror otrzymuję komunikat:

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

wiem, że gdybym typecast zarówno myf i mys jak int s kompilator będzie zadowolony, podobnie jak Mogę ustawić kilka z int s z wartościami z myf i mys i wykonać porównanie; ale dlaczego muszę je usunąć, aby usunąć ostrzeżenie? Dlaczego to ostrzeżenie istnieje w pierwszej kolejności? Musi być pewne niebezpieczeństwo w tym, że nie widzę.


UWAGA:
Czytałem dokumentację gcc tego enum-porównać flagą, ale to nie mówi wiele o niczym:

-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.

+2

Dokumentacja gcc jest dość objaśniająca. Co tam nie jest jasne? – SomeWittyUsername

+1

@icepack - * jak * jest to objaśniające? Mówi, co robi, nie mówi ani słowa o tym, dlaczego ** ktoś by tego potrzebował. Jeśli członkowie dwóch różnych wyliczeń są oba typu "int", dlaczego potrzebuję ostrzeżenia przy porównywaniu jednego int do innego int? – Mike

+0

Myślę, że to tylko ostrzeżenie, ponieważ może to łatwo być błędem. Jedyne, co mogę wymyślić, to to, że wyliczenia mogą być potencjalnie reprezentowane przez różne typy. – teppic

Odpowiedz

11

To nie jest ostrzeżenie ze względu na kwestię zgodności ze standardami, jest to jeden z ostrzeżeń "to nie wydaje się właściwe". Jeśli myślisz o typowych zastosowaniach wyliczeń, takie porównanie nie ma większego sensu w wielu przypadkach. Na przykład:

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

To się zgadza, ale ogólnie porównanie nie ma większego sensu. Jeśli wiesz, że masz na myśli, typecast przekona kompilator, jak zauważyłeś.

+0

Tak, ogólnie rzecz biorąc, ma to sens ... oczywiście w * moim * rzeczywistym użyciu jest to dużo bardziej sensowne niż dni czy miesiące, ale nie ma sposobu, żeby "gcc" to wiedział. ;) Nie sądzę, że jesteś świadomy sposobu wyłączenia '-Wumum-compare', gdy' -Wall' jest włączony? – Mike

+1

@Mike Spróbuj '-Wall -Wno-enum-compare' łącznie. To powinno dać ci "wszystkie" ostrzeżenia minus ostrzeżenie porównawcze enum. – FatalError

+3

Bah, który nadal używa niedzieli jako pierwszego dnia tygodnia? (+1, BTW) –

2

To ostrzeżenie, bo masz ostrzeżenie flaga na. Opis flagi nie wyjaśnia, dlaczego tak jest, ale prawdopodobnie można bezpiecznie założyć, że istnieje, aby zapobiec przypadkowym porównaniom różnych typów wyliczeń, ponieważ ten błąd to zwykle .

Co więcej, masz rację, że możesz używać wartości wyliczeniowych takich samych, jak możesz mieć stałe. A jeśli powiesz, że to if (myf == c), najprawdopodobniej nie wysłałbyś ostrzeżenia (mówię najprawdopodobniej dlatego, że nie eksperymentowałem, a GCC może zrobić to, co chce, z tym ostrzeżeniem, ale technicznie c jest po prostu stałą całkową i robi nie nosić typu enum second). Zamiast tego wyraźnie porównujesz dwie wartości różnych typów wyliczeniowych.

+1

'jeśli powiedziałeś, że jeśli (myf == c) to najprawdopodobniej nie wyrzuciłoby to ostrzeżenia' - interesująca teoria , Wypróbowałem to i nadal rzuca jedną (fyi). Ok, więc skoro potrzebuję '-Wall-Werror' utknąłem, robiąc typografię, w której zasadniczo nie jest potrzebna. – Mike

+1

@Mike - wystarczy skompilować z '-Wno-enum-compare'? – teppic

+0

@Mike: Ok, więc GCC bierze pod uwagę, że tak czy inaczej jest to możliwe. Niezbyt zaskakujące, ponieważ to ostrzeżenie dotyczy oznakowania czegoś, co nie jest technicznie nielegalne. –

1

Jest to ostrzeżenie, ale w przypadku kompilacji z -Wall-Werror wszystkie ostrzeżenia są traktowane jako błąd. Odpoczynek, możesz znaleźć coś podobnego.

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

odniesieniu

HIMS

+0

FYI, widziałem ten link podczas zamieszczania pytania, ale ponieważ język był inny, pytanie jest technicznie różne, a odpowiedzi tu nie mają sensu; Zignorowałem to. Powinien jednak wspomnieć o tym w pytaniu. – Mike

1

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

To powinno wystarczyć. Ale to jest brudna praktyka, używaj jej tylko wtedy, gdy obie wyrazy są różnymi "wersjami" tej samej grupy, tak jak nowsza zawierałaby nowe słowa kluczowe na końcu.

Powiązane problemy