Una pregunta simple: es enum { a } e = 1; ¿válido?
En otras palabras: la asignación de un valor, que no está presente en el conjunto de valores de las constantes de enumeración, ¿conduce a un comportamiento bien definido?
Manifestación:
$ gcc t0.c -std=c11 -pedantic -Wall -Wextra -c <nothing> $ clang t0.c -std=c11 -pedantic -Wall -Wextra -c <nothing> $ icc t0.c -std=c11 -pedantic -Wall -Wextra -c t0.c(1): warning #188: enumerated type mixed with another type # note: the same warning for enum { a } e = 0; $ cl t0.c /std:c11 /Za /c <nothing>Del estándar C18 en 6.7.2.2:
Cada tipo enumerado será compatible con char, un tipo entero con signo o un tipo entero sin signo. La elección del tipo está definida por la implementación, pero debe poder representar los valores de todos los miembros de la enumeración.
Entonces sí enum { a } e = 1; es válida. e es un tipo 'entero' por lo que puede tomar el valor 1 . El hecho de que 1 no esté presente como valor de enumeración no es un problema. Los miembros de la enumeración solo brindan identificadores útiles para algunos de los valores posibles.
No puedo encontrar ninguna referencia en este Borrador del Estándar C11 (en términos de "restricciones") que prohíba una asignación a un tipo de enum como el suyo (y el Estándar C18 citado en esta otra respuesta usa una redacción esencialmente idéntica).
Sin embargo, ese Borrador C11 sí proporciona esto, en el Anexo I - Advertencias comunes :
1 Una implementación puede generar advertencias en muchas situaciones, ninguna de las cuales se especifica como parte de esta Norma Internacional. Las siguientes son algunas de las situaciones más comunes.
2
…
— Se otorga un valor a un objeto de un tipo enumerado que no sea mediante la asignación de una constante de enumeración que sea miembro de ese tipo, o un objeto de enumeración que tenga el mismo tipo, o el valor de una función que devuelva el mismo tipo enumerado (6.7.2.2).
Pero esa advertencia sugerida podría aplicarse igualmente a una asignación como enum { a } e = 0; , donde el valor de RHS corresponde a una constante de enumeración válida pero en realidad no es ni una constante de enumeración del tipo ni un objeto de ese tipo enumerado.
Esto es válido en C según, por ejemplo, el borrador de trabajo 202x :
6.7.2.2/4 Cada tipo enumerado debe ser compatible con char, un tipo entero con signo o un tipo entero sin signo. La elección del tipo está definida por la implementación, pero debe ser capaz de representar los valores de todos los miembros de la enumeración.
particularmente debido al requisito de "tipo compatible":
6.2.7/1 Dos tipos tienen un tipo compatible si sus tipos son iguales . Reglas adicionales [...]
Si bien está fuera del alcance de estas preguntas y respuestas (etiqueta C, no C ++), puede ser interesante señalar que lo mismo no se aplica a C ++, donde las enumeraciones sin ámbito de "estilo C" sin tipo subyacente fijo tienen diferencias sutiles de C. Para detalles sobre el caso de C++, consulte las siguientes preguntas y respuestas: