2015-07-01 10 views
21

Ho il seguente codice.Perché "typeof enum constant" genera un avviso se confrontato con una variabile di tipo enum?

typedef enum {FOO, BAR} Baz; 

int main() 
{ 
    Baz f1 = FOO; 
    typeof(FOO) f2 = FOO; 
    return (f1 == f2); 
} 

mio compilazione utilizzando gcc -Wextra foo.c genera un avviso dicendo

foo.c: In function ‘main’: 
foo.c:7:13: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] 
return (f1 == f2); 
      ^

La mia versione di gcc

gcc --version 
gcc (Ubuntu 4.9.2-10ubuntu13) 4.9.2 

Come posso risolvere questo problema?

+1

http: // stackoverflow.it/questions/10582523/how-are-integer-types-converted-implicitamente (duplicato errato, poiché la risposta accettata non è corretta) – Lundin

+3

Vale la pena notare che 'typeof' è un'estensione specifica di gcc. –

risposta

20

Citando direttamente C11, capitolo §6.7.2.2, enumerazione specificatori,

Ciascun tipo enumerato sono compatibili con char, un tipo intero con segno, o un tipo intero senza segno. La scelta del tipo è definita dall'implementazione.

Così, il tipo della variabile enum non è definita dalla norma. Può essere uno qualsiasi dei precedenti.

OTOH, FOO essendo una costante enumerazione, typeof(FOO) vi darà int, come i mandati standard di

un identificatore dichiarata come costante di enumerazione è di tipo int.

che viene utilizzato come tipo per f2.

Ora, se enum è unsigned int sulla vostra implementazione, così è f1 e, f2 è int.

Successivamente, viene visualizzato l'avviso.

Come posso risolvere questo problema?

Beh, se si cambia il tipo di f2 a typeof(Baz), che dà il tipo di enum, allora entrambi i tipi di f1 e f2 sarà lo stesso. Il compilatore sarà felice.

SEE LIVE HERE

+0

Ho effettuato un aggiornamento minore. Il tipo enumerato può essere compatibile con 'char' o con * qualsiasi * tipo intero con segno o senza segno. –

16

E 'un noto "bug" nello standard C. Enumerazione costanti sono garantite di tipo int, mentre le variabili di enumerazione sono di tipo intero definito dall'implementazione.

See this per riferimenti.

+0

Perché lo fanno invece di lasciare semplicemente applicare le normali regole di promozione (cioè possono essere di qualsiasi tipo che promuova ad int)? – Random832

+0

@ Random832 Nessun razionale è mai stato fornito in standard C90 o successivi. Suppongo che vorrebbero salvare la memoria consentendo l'enumerazione di dimensioni in byte, inoltre in teoria sarebbe utile avere un enum di un byte in molti casi. In pratica, non si può mai scrivere codice che si basi su di esso, perché tale codice sarebbe non portatile. Questa è solo una delle tante cose stupide nello standard C, proprio come per esempio le varie regole di promozione implicite del tipo. – Lundin

+0

Sì, ma un byte può promuovere un int. Quindi, in pratica, in quasi tutte le espressioni FOO si comporterebbe ancora come un int anche se il suo tipo è veramente quello dell'enumerazione. – Random832

Problemi correlati