Nella prima istanza, il compilatore stesso sta provando a selezionare un numero intero che sta causando un overflow, e quindi ti avvisa. È probabile che produca INT_MIN
. Lo standard consente a qualsiasi valore in un signed int
di essere una costante enum (vedere in basso).
Nel secondo, l'espressione (INT_MAX + 1)
viene calcolata prima che venga assegnata a out_2
. Un overflow nell'espressione qui sta producendo un risultato che è permesso, ma questo è un comportamento indefinito. Il risultato valido viene quindi memorizzato nell'enumerazione, motivo per cui non viene prodotto il primo errore.
clang (3,2) anche non avvertire di questo, che è effettivamente identica:
int a = INT_MAX + 1;
A questo proposito, clang non si comporta secondo lo standard C, in quanto questo è indefinito.
L'uscita dal gcc in confronto fa la differenza completamente chiaro:
In function ‘main’:
9:9: error: overflow in enumeration values
13:25: warning: integer overflow in expression [-Woverflow]
Il compilatore Intel ignora l'overflow enum, ma avverte circa l'overflow integer:
enum.c(13): warning #61: integer operation result is out of range
out_2 = INT_MAX + 1
^
Per riferimento, dallo standard C99 6.7.7.2.2, "L'espressione che definisce il valore di una costante di enumerazione deve essere un'espressione costante intera che ha un valore rappresentabile come
int
; .3," T identifica gli elenchi di un elenco di enumeratori come costanti che hanno tipo
int
e possono apparire ovunque siano consentiti. "Ad esempio, una costante enum può essere qualsiasi valore
int
e ha un tipo
int
. Il tipo risultante di una variabile enum definita può essere
char
,
int
o
unsigned int
, purché consenta tutte le possibili costanti nell'enumerazione. Di conseguenza, sia
enums
nell'esempio non sono definiti, in quanto entrambi richiedono un overflow di numeri interi. Il primo è esplicitamente illegale.
Abbastanza sicuro che lo standard non definisca l'intervallo di un 'enum'. – asveikau
La mia ipotesi: prima valuta INT_MAX + 1, che si avvolge e assegna a out_2. –
@johnny: no, richiama UB. –